[英]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.