我对SAS PROC SQL中的以下2个代码有疑问。
代码1 :(标准图书版本)
CREATE TABLE WORK.OUTPUT AS
SELECT
"CLAIM" AS SOURCE,
a.CLAIMID,
a.DXCODE
FROM
DW.CLAIMS_BAV AS a
WHERE
a.SITEID = '0001'
AND a.CLAIMID IN (SELECT CLAIMID FROM WORK.INPUT)
代码2 :(实践中更快的方法)
CREATE TABLE WORK.OUTPUT AS
SELECT
"CLAIM" AS SOURCE,
a.CLAIMID,
a.DXCODE
FROM
DW.CLAIMS_BAV AS a
WHERE
a.SITEID = '0001'
AND a.CLAIMID IN ('10001', '10002', '10003', ... '15000')
当我尝试通过在#1中使用子查询来更优雅地执行此操作时,运行时间会超过50分钟。但是使用代码2在3分钟内返回了相同的输入。为什么?注意,使用INNER JOIN(after reading this)也同样慢。输入的是5000+ CLAIMID,我每天手动将其粘贴到IN('...')块中。
PS:CLAIMID是虚构的,在现实生活中它们是随机的。
CLAIMID在DW.CLAIMS中建立索引。我正在使用SAS PROC SQL访问Oracle数据库。发生了什么,还有更好的方法吗?谢谢!
最佳答案
我不知道我能不能告诉您为什么SAS在初选时这么慢?在那种情况下,显然没有优化的地方。
如果我不得不猜测,我猜想SAS在第一种情况下决定不能使用直通SQL,因此它先下载整个大表,然后在SAS端运行,而在第二种情况下是将查询传递到SQL数据库,并且仅将结果行传输回去。
但是无论如何,有几种方法可以解决此问题。这是一个:使用宏变量精确地进行粘贴!
proc sql;
select quote(strip(claimid)) into :claimlist separated by ','
from work.input
;
CREATE TABLE WORK.OUTPUT AS
SELECT
"CLAIM" AS SOURCE,
a.CLAIMID,
a.DXCODE
FROM
DW.CLAIMS_BAV AS a
WHERE
a.SITEID = '0001'
AND a.CLAIMID IN (&claimlist.)
;
quit;
Tada,您不必再碰这个了,它与您执行的复制/粘贴相同。
一些额外的注释给出了一些评论:
如果CLAIMID小于15,则可能会有空格填充,因此我添加了
strip
来删除这些填充。字符串比较并不重要-除非您可能用尽了宏语言,否则我担心某些DBMS可能实际上关心填充。如果15是恒定长度,则可以省略strip
。宏变量在空间上最多可运行64K。如果您有15个字符变量加上“”两个加逗号1,则您有18个字符;您可以容纳3500个以上的值。不幸的是,这个数字还不到5000。
在这种情况下,您可以将字段拆分为两个宏变量(希望很容易,请使用
obs
和firstobs
),或者可以执行其他一些解决方案。work.input
数据集转移到DW
libname中,然后在其中执行SQL连接。 %include
该文件。 call execute
执行整个proc SQL。 这是CALL EXECUTE的一个示例。
data _null_;
set work.input end=eof;
if _n_=1 then do;
call execute('CREATE TABLE WORK.OUTPUT AS
SELECT
"CLAIM" AS SOURCE,
a.CLAIMID,
a.DXCODE
FROM
DW.CLAIMS_BAV AS a
WHERE
a.SITEID = "0001"
AND a.CLAIMID IN ('); *the part of the SQL query before the list of IDs;
end;
call execute(quote(claimID) || ' ');
if EOF then do;
call execute('); QUIT;'); *the part of the SQL query after the list of IDs;
end;
run;
实际上,这与
%INCLUDE
解决方案几乎完全相同,除了您将填充的put
填充到文本文件中,而不是对其进行CALL EXECUTE
编码之后,再对文本文件进行%INCLUDE
。关于sas - SAS PROC SQL:在对IN()进行硬编码时,为什么会有不同?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47099028/