[英]SAS/PROC-SQL Convert from table with unique key to table with multiple rows has the same key
目前我有一個如下表:
U_ID SPOUSEDOB FCHILDDOB SCHILDDOB ChangeDate
1 20/01/1980 01/01/1900 01/01/1900 01/01/2000
2 20/01/1950 20/01/1970 01/01/1900 01/01/2000
3 20/01/1960 20/01/1990 20/01/1995 01/01/2000
1 20/01/1980 20/01/1995 01/01/1900 01/01/2005
1 20/01/1980 20/01/1995 20/01/2006 01/01/2010
日期01/01/1900,這意味着沒有配偶/子女。 我想將此表轉換如下:
Member_ID U_ID Relation DOB ChangeDate
1 1 Spouse 20/01/1980 01/01/2000
2 2 Spouse 20/01/1950 01/01/2000
3 2 Child 20/01/1970 01/01/2000
4 3 Spouse 20/01/1960 01/01/2000
5 3 Child 20/01/1990 01/01/2000
6 3 Child 20/01/1995 01/01/2000
7 1 Child 20/01/1995 01/01/2005
8 1 Child 20/01/2006 01/01/2010
但是這個表仍然無法提供在特定時間(01/01/2006)和(01/01/2011)回答這個問題的最佳方法,用戶1有多少孩子? 答案是1和2.我也發現很難從表1轉換到表2,我堅持如何為同一個user_id創建新行。 有關如何改善這種情況或解決轉換表問題的任何想法? 非常感謝幫助。 先感謝您。
這會將您的表從第一種格式轉換為第二種格式:
SELECT
U_ID,
'Spouse' Relation,
Spousedob DOB,
MIN(STR_TO_DATE(ChangeDate, '%d/%m/%Y')) ChangeDate
FROM
yourtable
WHERE
Spousedob != '01/01/1900'
GROUP BY U_ID
UNION ALL
SELECT
U_ID,
'Child' Relation,
FCHILDDOB DOB,
MIN(STR_TO_DATE(ChangeDate, '%d/%m/%Y')) ChangeDate
FROM
yourtable
WHERE FCHILDDOB != '01/01/1900'
GROUP BY U_ID
UNION ALL
SELECT
U_ID,
'Child' Relation,
SCHILDDOB DOB,
MIN(STR_TO_DATE(ChangeDate, '%d/%m/%Y')) ChangeDate
FROM yourtable
WHERE SCHILDDOB != '01/01/1900'
GROUP BY U_ID
ORDER BY ChangeDate, U_ID
但要回答您的問題,您可以使用此查詢:
SELECT (FCHILDDOB!='01/01/1900')+(SCHILDDOB!='01/01/1900')
FROM yourtable
WHERE
(U_ID, ChangeDate) IN (
SELECT U_ID, MAX(ChangeDate)
FROM yourtable
WHERE
U_ID=1 AND MIN(STR_TO_DATE(ChangeDate, '%d/%m/%Y'))<'2011-01-01')
(我在考慮你的日期存儲為varchar,我正在使用STR_TO_DATE轉換為日期)
編輯
您可以使用列創建一個表yourtable2
(Member_ID auto_increment,U_ID,Relation,DOB,ChangeDate),然后使用以下命令將所有數據從yourtable
插入yourtable2
:
INSERT INTO yourtable2 (U_ID, Relation, DOB, ChangeDate)
SELECT ... --- the select query above
ORDER BY ChangeDate, DOB, U_ID
然后計算您可以使用的孩子的名字:
SELECT COUNT(*)
FROM yourtable2
WHERE Relation='Child'
AND U_ID=1
AND ChangeDate <= '2011-01-01'
請看這里的小提琴。
這不起作用,因為我不理解你的起始表中的關系。 但它可能會幫助您找到使用普通舊SAS數據步驟代碼的另一種解決方案:
data have;
input U_ID SPOUSEDOB :ddmmyy10. FCHILDDOB :ddmmyy10.
SCHILDDOB :ddmmyy10. ChangeDate :ddmmyy10.;
datalines;
1 20/01/1980 01/01/1900 01/01/1900 01/01/2000
2 20/01/1950 20/01/1970 01/01/1900 01/01/2000
3 20/01/1960 20/01/1990 20/01/1995 01/01/2000
1 20/01/1980 20/01/1995 01/01/1900 01/01/2005
1 20/01/1980 20/01/1995 20/01/2006 01/01/2010
run;
data want(keep=Member_ID U_ID Relation DOB ChangeDate);
attrib Member_ID length=8;
attrib U_ID length=8;
attrib Relation length=$6;
attrib DOB length=8 format=ddmmyy10.;
attrib ChangeDate length=8 format=ddmmyy10.;
retain Member_ID 0;
set have;
if _n_ = 1 or U_ID ne 1 then do;
Member_ID + 1;
Relation = 'Spouse';
DOB = SPOUSEDOB;
output;
end;
if FCHILDDOB ne mdy(1,1,1900) then do;
Member_ID + 1;
Relation = 'Child';
DOB = FCHILDDOB;
output;
end;
if SCHILDDOB ne mdy(1,1,1900) then do;
Member_ID + 1;
Relation = 'Child';
DOB = SCHILDDOB;
output;
end;
run;
這是一個簡單的SAS datastep。 您可以調整它以使用VNAME()來定義關系(取決於您的其他變量的命名方式); 例如,
relation = vname(DOBs[_t]);
然后使用SUBSTR或其他任何內容將其縮短為正確的文本。 除此之外,它應該足夠靈活,以處理初始HAVE數據集中的任意數量的關系。
data want;
set have;
array DOBs SPOUSEDOB FCHILDDOB SCHILDDOB;
do _t = 1 to dim(DOBs);
if DOBs[_t] ne '01JAN1900'd then do;
relation=ifc(_t=1,'Spouse','Child'); *this could also be done using VNAME() to be more flexible;
DOB=DOBs[_t];
output;
end;
end;
keep relation DOB ChangeDate U_ID;
format DOB Changedate Date9.;
run;
proc sort data=want;
by u_id descending relation dob changedate;
run;
data final;
set want;
by u_id descending relation dob changedate;
if first.dob;
run;
然后處理它以僅選擇在特定日期出生的人,如果您更喜歡使用SQL,則可以使用查詢fthiella發布,或者您可以在SAS過程中進行過濾,例如:
proc means data=final;
where dob le '01JAN2006'd;
class relation;
var (whatever);
run;
或者使用ChangeDate,如果這是你要過濾的而不是實際的DOB。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.