匹配 table 中不同变量的最后一个值
Match last values of different variables from a table
我有一个 table 存储不同日期的 A 和 B 的值。它看起来像这样:
Date Amount Type
2015 15 A
2014 -3 B
2013 8 B
2013 10 A
2012 5 A
等
如何最有效地准备一个table,列出每个日期的当前 A 值和当前 B 值?这个想法是,对于每个日期,直接指定一个值,但另一个值需要是前一个值。
Date A B
2015 15 -3
2014 10 -3
2013 10 8
等等
数据集将是一个庞大的数据集(数百万条记录),非常感谢您的帮助。该解决方案将在 SAS 中实施,因此我将使用 SAS 过程或 proc sql 过程(它在自连接方面有其局限性)。
基本上,您想为每个案例重新加入 table。
我不清楚你决定是使用当前还是以前的A金额或B金额的逻辑是什么,但你应该可以在下面的声明中填写它。
select distinct <br>
dates.[date]<br>
, CASE WHEN {condition for A} THEN currentA.amount ELSE prevA.amount END as A<br>
, CASE WHEN {condition for B} THEN currentB.amount ELSE prevB.amount END as B<br>
from myTable dates<br>
LEFT OUTER JOIN myTable currentA on dates.[date] = currentA.[date] and currentA.[type] = 'A'<br>
LEFT OUTER JOIN myTable currentB on dates.[date] = currentB.[date] and currentB.[type] = 'B'<br>
LEFT OUTER JOIN myTable prevA on dates.[date]-1 = prevA.[date] and prevA.[type] = 'A'<br>
LEFT OUTER JOIN myTable prevB on dates.[date]-1 = prevB.[date] and prevB.[type] = 'B'<br>
order by dates.[date] desc<br>
为了获得更好的性能,您可以将日期分组到临时 table 并将其用于开始 table 而不是使用 distinct 关键字。我在这里没有这样做是为了使查询简短。
data have;
input Date Amount Type $;
cards;
2015 15 A
2014 -3 B
2013 8 B
2013 10 A
2012 5 A
;
data want(keep=date A B);
merge have have(firstobs=2 rename=(date=_date amount=_amount type=_type));
retain flag;
if date-_date=1 then do;
if flag=1 then do;
call missing(flag);
return;
end;
if type='A' then do;
A=amount;
B=_amount;
end;
else if type='B' then do;
B=amount;
A=_amount;
end;
output;
end;
else if date=_date then do;
flag=1;
if type='A' then do;
A=amount;
B=_amount;
end;
else if type='B' then do;
B=amount;
A=_amount;
end;
output;
end;
else if missing(_date) then do;
if flag=1 then return;
if type='A' then A=amount;
else B=amount;
output;
end;
run;
正如 Gordon 在评论中所说,我会使用数据步骤和 RETAIN
语句
首先,创建数据集。
其次,按日期升序排列
第三,使用数据步骤和 RETAIN
来创建您的值。使用 BY 语句和子集 IF
输出给定日期的所有值。
最后,按 DATE 降序排序,给你想要的顺序。
data have;
input Date Amount Type $;
datalines;
2015 15 A
2014 -3 B
2013 8 B
2013 10 A
2012 5 A
;
run;
proc sort data=have;
by date;
run;
data want(keep=date a b);
set have;
by date;
retain a b;
if Type = "A" then
a = amount;
else if Type = "B" then
b = amount;
if last.date;
run;
proc sort data=want;
by descending date;
run;
这会产生:
我有一个 table 存储不同日期的 A 和 B 的值。它看起来像这样:
Date Amount Type
2015 15 A
2014 -3 B
2013 8 B
2013 10 A
2012 5 A
等
如何最有效地准备一个table,列出每个日期的当前 A 值和当前 B 值?这个想法是,对于每个日期,直接指定一个值,但另一个值需要是前一个值。
Date A B
2015 15 -3
2014 10 -3
2013 10 8
等等
数据集将是一个庞大的数据集(数百万条记录),非常感谢您的帮助。该解决方案将在 SAS 中实施,因此我将使用 SAS 过程或 proc sql 过程(它在自连接方面有其局限性)。
基本上,您想为每个案例重新加入 table。
我不清楚你决定是使用当前还是以前的A金额或B金额的逻辑是什么,但你应该可以在下面的声明中填写它。
select distinct <br>
dates.[date]<br>
, CASE WHEN {condition for A} THEN currentA.amount ELSE prevA.amount END as A<br>
, CASE WHEN {condition for B} THEN currentB.amount ELSE prevB.amount END as B<br>
from myTable dates<br>
LEFT OUTER JOIN myTable currentA on dates.[date] = currentA.[date] and currentA.[type] = 'A'<br>
LEFT OUTER JOIN myTable currentB on dates.[date] = currentB.[date] and currentB.[type] = 'B'<br>
LEFT OUTER JOIN myTable prevA on dates.[date]-1 = prevA.[date] and prevA.[type] = 'A'<br>
LEFT OUTER JOIN myTable prevB on dates.[date]-1 = prevB.[date] and prevB.[type] = 'B'<br>
order by dates.[date] desc<br>
为了获得更好的性能,您可以将日期分组到临时 table 并将其用于开始 table 而不是使用 distinct 关键字。我在这里没有这样做是为了使查询简短。
data have;
input Date Amount Type $;
cards;
2015 15 A
2014 -3 B
2013 8 B
2013 10 A
2012 5 A
;
data want(keep=date A B);
merge have have(firstobs=2 rename=(date=_date amount=_amount type=_type));
retain flag;
if date-_date=1 then do;
if flag=1 then do;
call missing(flag);
return;
end;
if type='A' then do;
A=amount;
B=_amount;
end;
else if type='B' then do;
B=amount;
A=_amount;
end;
output;
end;
else if date=_date then do;
flag=1;
if type='A' then do;
A=amount;
B=_amount;
end;
else if type='B' then do;
B=amount;
A=_amount;
end;
output;
end;
else if missing(_date) then do;
if flag=1 then return;
if type='A' then A=amount;
else B=amount;
output;
end;
run;
正如 Gordon 在评论中所说,我会使用数据步骤和 RETAIN
语句
首先,创建数据集。
其次,按日期升序排列
第三,使用数据步骤和 RETAIN
来创建您的值。使用 BY 语句和子集 IF
输出给定日期的所有值。
最后,按 DATE 降序排序,给你想要的顺序。
data have;
input Date Amount Type $;
datalines;
2015 15 A
2014 -3 B
2013 8 B
2013 10 A
2012 5 A
;
run;
proc sort data=have;
by date;
run;
data want(keep=date a b);
set have;
by date;
retain a b;
if Type = "A" then
a = amount;
else if Type = "B" then
b = amount;
if last.date;
run;
proc sort data=want;
by descending date;
run;
这会产生: