簡體   English   中英

將 SQL 更新轉換為 SAS DI

[英]Translating a SQL update to SAS DI

假設我們有一個表P_DEF ,我們想在其中更新存儲在另一個表TMP的某個子集的列RUN_ID的值。 這里我將如何在 SQL 中做到這一點:

update P_DEF
set RUN_ID = (-1) * TMP.RUN_ID /* change the sign of the value */
from P_DEF
inner join TMP
on P_DEF.RUN_ID = TMP.RUN_ID
and P_DEF.ITEM_ID = TMP.ITEM_ID
and P_DEF.ITEM_TITLE = TMP.ITEM_TITLE

現在最大的問題是:據我所知, proc SQL不支持這種過濾更新 那么如何在 SAS DI(S) 中使用最少的轉換來做到這一點?

SAS SQL 不支持通過連接更新,但您可以執行相關更新:通過相關子查詢的值更新:

data P_DEF;
infile cards;
length RUN_ID_ORIG 8;
input RUN_ID ITEM_ID ITEM_TITLE $20.;
RUN_ID_ORIG = RUN_ID;
cards;
1 1 some title
1 1 should be negative
1 2 another title
1 3 should be negative
4 44 another title
5 44 should be negative
;
run;

data TMP;
infile cards;
input RUN_ID ITEM_ID ITEM_TITLE $20. @30 NEW_ID;
cards;
1 1 should be negative       100
1 3 should be negative       123
5 44 should be negative      188
;
run;

proc sql;
/* this unwillingly updates all records, nonmatched will be set to null */
update P_DEF
set RUN_ID = (select NEW_ID from TMP
            where P_DEF.RUN_ID = TMP.RUN_ID
            and P_DEF.ITEM_ID = TMP.ITEM_ID
            and P_DEF.ITEM_TITLE = TMP.ITEM_TITLE )
;
select * from P_DEF
;
quit;

當存在不匹配時,相關更新是不夠的,因此您需要添加過濾器以僅更新匹配的行。 在加入多列時,我通常依靠 catx 來獲取唯一值(根據您的數據,您可能需要在 put 函數中使用不同的數字格式):

proc sql;
update P_DEF set RUN_ID = RUN_ID_ORIG; /* reset RUN_ID */
quit;


/* correct "inner join" update */
proc sql;
update P_DEF
set RUN_ID = (select NEW_ID from TMP
            where P_DEF.RUN_ID = TMP.RUN_ID
            and P_DEF.ITEM_ID = TMP.ITEM_ID
            and P_DEF.ITEM_TITLE = TMP.ITEM_TITLE )
where
          catx('#', put(RUN_ID, 16.), put(ITEM_ID, 16.), ITEM_TITLE)
in select catx('#', put(RUN_ID, 16.), put(ITEM_ID, 16.), ITEM_TITLE)
from TMP
;
select * from P_DEF;
quit;

上面的版本與您的確切示例略有不同,以展示如何從子查詢中獲取值 - NEW_ID 列。

僅使用查找表來標識要更新的行的簡化版本是這樣的:

proc sql;
update P_DEF set RUN_ID = RUN_ID_ORIG; /* reset RUN_ID */
quit;

proc sql;
/* simplified for your case:
you dont actually use value from TMP that does not exist in P_DEF */
update P_DEF
set RUN_ID = -1 * RUN_ID
where
   RUN_ID > 0 /* so we can rerun this if needed */
   and      catx('#', put(RUN_ID, 16.), put(ITEM_ID, 16.), ITEM_TITLE)
in ( select catx('#', put(RUN_ID, 16.), put(ITEM_ID, 16.), ITEM_TITLE)
from TMP )
;
select * from P_DEF;
quit;

如您所見,相關更新可能需要兩個子查詢來更新單個列,因此不要指望它在更大的表上也能執行。 您可能更適合使用數據步驟方法:MERGE、MODIFY 或 UPDATE 語句。

至於您要求的 SAS Data Integration Studio 轉換,我相信您可以使用 SCD Type 1 Loader 實現這一點,這將生成我提到的一些代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM