如何解决SQL:获取最近一个月的N和这些记录的历史记录
我想查找最近一段时间的前N个名字(值最高的名字)。对于这些名称,我想获得历史价值。
此问题Select top 10 records for each category
我尝试了以下操作:
base_table (period,name,value)
CREATE VIEW TOP3 AS
SELECT DISTINCT a.*,COUNT(*) as rank
FROM base_table AS a
LEFT JOIN base_table AS a2
ON a.period = a2.period and a.value <= a2.value
GROUP BY a.value
HAVING COUNT(*) <= 3
ORDER BY period,rank;
这使我成为每个时期的前三名。
period | name | value | rank
092020 Joe 100 1
092020 Jane 90 2
092020 Doe 80 3
082020 Jan 100 1
082020 Doc 99 2
082020 Pete 98 3
.
.
.
但不是理想的结果。
假设这些是最近一个月的前三名:
period | name | value | rank
092020 Joe 100 1
092020 Jane 90 2
092020 Doe 80 3
现在,我希望获得这些的历史记录,即使它们不在上个月的前3名中,也是如此:
period | name | value | rank
092020 Joe 100 1
092020 Jane 90 2
092020 Doe 80 3
082020 Joe 95 4
082020 Jane 94 5
082020 Doe 7 50
. . . .
. . . .
. . . .
092019 Joe 42 20
092019 Doe 34 35
092019 Jane 1 100
仅供参考,我正在使用PROC SQL在SAS中工作,因此对我而言,诸如CTE,窗口函数和其他内容之类的细腻内容对我不可用。
解决方法
您可以使用JOIN
:
SELECT a.*,ar.rank
FROM base_table a JOIN
(SELECT a.value,COUNT(*) as rank
FROM base_table a JOIN
base_table a2
ON a.period = a2.period and a.value <= a2.value JOIN
(SELECT max(a3.period) as max_period
FROM base_table a3
) a3
ON a3.max_period = period
GROUP BY a.value
HAVING COUNT(*) <= 3
) ar
ON ar.value = a.value
ORDER BY period,rank;
我怀疑使用data
步骤会更简单,至少对于分配等级而言。
您可以尝试使用子查询吗?如果不是这样,您可以创建一个视图,而不是使用一些row_number()/ rank函数进行排序
SELECT b.period,b.name,b.value
FROM base_table b
INNER JOIN
(
-- subquery to get last period
SELECT TOP 3 name,period,value
FROM base_table
WHERE period = (SELECT MAX(period) FROM base_table)
ORDER BY 3 DESC
) AS s ON s.name = b.name -- join them
,
不确定为什么要为此使用SQL。这是使用PROC SQL的OUTOBS选项的方法。
首先让我们做一些实际的测试数据:
data have ;
input period :ddmmyy. name $ value rank ;
format period yymm7. ;
cards;
01092020 Joe 100 1
01092020 Jane 90 2
01092020 Doe 80 3
01082020 Joe 95 4
01082020 Jane 94 5
01082020 Doe 7 50
01092019 Joe 42 20
01092019 Doe 34 35
01092019 Jane 1 100
;
现在让我们将N设置为宏变量以使其更具灵活性。由于示例数据仅包含3个名称,因此我们使用N的2。
%let n=2;
因此,首先找到最近(最大)时间段的前N个。
proc sql;
reset outobs=&n;
create table top&n as select name
from have
having period=max(period)
order by value desc
;
现在将OUTOBS重置为MAX,并使用该TOPn列表从这些名称的原始数据集中提取所有数据。
reset outobs=max;
create table want as
select * from have
where name in (select name from top&n)
;
quit;
让我们看看结果:
proc print data=want;
run;
哪个是
Obs period name value rank
1 2020M09 Joe 100 1
2 2020M09 Jane 90 2
3 2020M08 Joe 95 4
4 2020M08 Jane 94 5
5 2019M09 Joe 42 20
6 2019M09 Jane 1 100
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。