我有一个工作多年的计划。今天,我们从SAS 9.4M3升级到9.4M7。
proc setinit
Current version: 9.04.01M7P080520从那以后,我无法获得与升级前相同的结果。
请注意,我正在直接查询Oracle数据库。
为了用一个最小的、可重复的SAS表示例来复制这个问题,我发现这个问题在查询SAS表而不是在Oracle数据库上时消失了。
假设我有以下数据集:
data have;
infile datalines delimiter="|";
input name :$8. id $1. value :$8. t1 :$10.;
datalines;
Joe|A|TLO
Joe|B|IKSK
Joe|C|Yes
;使用临时表:
proc sql;
create table want as
select name,
min(case when id = "A" then value else "" end) as A length 8
from have
group by name;
quit;
Results:
name A
Joe TLO但是,当直接在oracle数据库上运行相同的查询时,我会得到一个缺失的值:
proc sql;
create table want as
select name,
min(case when id = "A" then value else "" end) as A length 8
from have_oracle
group by name;
quit;
name A
Joe 根据文档,当在SAS表上使用时,min()函数运行正常。
-- MIN函数只有在所有参数都缺少时才返回缺少的值(.) 。
我相信,当Oracle不理解SAS传递它的函数时,就会发生这种情况-- SAS和Oracle中的min函数非常不同,在SAS中的等效函数是LEAST()。
因此,我的猜测是,升级将如何将SAS函数转换为Oracle,但这仍然是一个猜测。有人遇到过这种行为吗?
编辑:@Richard的评论
options sastrace=',,,d' sastraceloc=saslog nostsuffix;
proc sql;
create table want as
select t1.name,
min(case when id = 'A' then value else "" end) as A length 8
from oracle_db.names t1 inner join oracle_db.ids t2 on (t1.tid = t2.tid)
group by t1.name;
ORACLE_26: Prepared: on connection 0
SELECT * FROM NAMES
ORACLE_27: Prepared: on connection 1
SELECT UI.INDEX_NAME, UIC.COLUMN_NAME FROM USER_INDEXES UI,USER_IND_COLUMNS UIC WHERE UI.TABLE_NAME='NAMES' AND
UIC.TABLE_NAME='NAMES' AND UI.INDEX_NAME=UIC.INDEX_NAME
ORACLE_28: Executed: on connection 1
SELECT statement ORACLE_27
ORACLE_29: Prepared: on connection 0
SELECT * FROM IDS
ORACLE_30: Prepared: on connection 1
SELECT UI.INDEX_NAME, UIC.COLUMN_NAME FROM USER_INDEXES UI,USER_IND_COLUMNS UIC WHERE UI.TABLE_NAME='IDS' AND
UIC.TABLE_NAME='IDS' AND UI.INDEX_NAME=UIC.INDEX_NAME
ORACLE_31: Executed: on connection 1
SELECT statement ORACLE_30
ORACLE_32: Prepared: on connection 0
select t1."NAME", MIN(case when t2."ID" = 'A' then t1."VALUE" else ' ' end) as A from
NAMES t1 inner join IDS t2 on t1."TID" = t2."TID" group by t1."NAME"
ORACLE_33: Executed: on connection 0
SELECT statement ORACLE_32
ACCESS ENGINE: SQL statement was passed to the DBMS for fetching data.
NOTE: Table WORK.SELECTED_ATTR created, with 1 row and 2 columns.
! quit;
NOTE: PROCEDURE SQL used (Total process time):
real time 0.34 seconds
cpu time 0.09 seconds发布于 2021-12-22 11:50:10
使用SASTRACE=系统选项记录发送给DBMS的SQL语句。
options SASTRACE=',,,d';将提供最详细的日志记录。
从准备好的语句中,您可以看到为什么要从Oracle查询中获得空白。
select
t1."NAME"
, MIN ( case
when t2."ID" = 'A' then t1."VALUE"
else ' '
end
) as A
from
NAMES t1 inner join IDS t2 on t1."TID" = t2."TID"
group by
t1."NAME"SQL ()聚合函数将排除空值。
在SQL中,空白值也被解释为null。
在SAS中,SQL查询返回min非空值TLO。
在Oracle查询中,SAS空白''被转换为' ' (一个空字符),该字符为非空字符,因此' ' < 'TLO'和您将得到空白结果。
在甲骨文中要强制执行的实际分钟是min(case when id = "A" then value else null end),@Tom通过省略子句显示这一点是可能的。
查看实际差异的唯一方法是在前面的SAS版本中使用跟踪运行查询,或者如果幸运的话,请参阅(许多人忽略的) "What's New“文档中的解释。
发布于 2021-12-22 13:59:53
为什么要使用' '或''作为其他值?也许Oracle对带有空格的字符串的处理方式与空字符串不同。
为什么不在clause子句中使用null呢?
或者干脆去掉off子句,让它默认为null。
libname mylib oracle .... ;
proc sql;
create table want as
select name
, min(case when id = "A" then value else null end) as A length 8
from mylib.have_oracle
group by name
;
quit;还可以尝试自己运行Oracle代码,而不是使用隐式pass。
proc sql;
connect to oracle ..... ;
create table want as
select * from connection to oracle
(
select name,
min(case when id = "A" then value else null end) as A length 8
from have_oracle
group by name
)
;
quit;发布于 2021-12-22 10:15:11
当我试图在Oracle中复制这个结果时,我得到了您正在寻找的结果,因此我怀疑它与SAS有关(我不熟悉)。
with t as (
select 'Joe' name, 'A' id, 'TLO' value from dual union all
select 'Joe' name, 'B' id, 'IKSK' value from dual union all
select 'Joe' name, 'C' id, 'Yes' value from dual
)
select name
, min(case when id = 'A' then value else '' end) as a
from t
group by name;
NAME A
---- ----
Joe TLO如果您只对id = 'A‘感兴趣,那么更好的查询是:
select name
, min(value) as a
from t
where id = 'A'
group by name;https://stackoverflow.com/questions/70446875
复制相似问题