我有一些可以这样表示的数据:
CREATE TABLE #foo (
id INT
, year INT
, value INT
, date Date
)
INSERT INTO #foo (id, year, value, date)
VALUES (1, 1, 1, '2001-01-01')
, (1, 2, 2, '2002-01-01')
, (1, 2, 3, '2002-02-01')
, (1, 2, 2, '2003-03-01') -- a year later!
, (1, 3, 2, '2003-01-01')
, (1, 3, 2, '2003-03-01')
基本上,我具有通过ID标识的一些公司的财务数据(在这种情况下,仅显示单个公司)。这些数据来自公司不时进行的披露,我拥有财务数据相关的年份以及相关财务报告的日期。
请注意,给定年份我可能有多个报告。这是因为公司可能会注意到他们先前报告的内容存在错误,并提交了“重述”以纠正这些错误。在某些情况下,即使在提交了下一个期间的结果之后,也可能要经过很长时间才能进行这些更正(例如,在这种情况下,第二年的最新报告在第三年的第一份报告之后)。
现在,我想确定过去任何给定日期知道的数据。显然,这涉及过滤在该日期之后给出的所有内容,而且还丢弃所有自此之后已得到纠正的“过时”报告(通过在“截止日期”之前重述)。
我所做的最好的事情是:(*我发誓仅用于此问题)
SELECT id, year, value, date
FROM (
SELECT *
, ROW_NUMBER() OVER (PARTITION BY id, year
ORDER BY date DESC) AS recency
FROM (
SELECT *
FROM #foo
WHERE date <= '2002-02-01'
) x
) y
WHERE recency = 1
-- | id | year | value | date |
-- |----|------|-------|------------|
-- | 1 | 1 | 1 | 2001-01-01 |
-- | 1 | 2 | 3 | 2002-02-01 |
首先,丢弃我截至日期(2002-02-01)之前的所有内容,然后使用每对(id,year)对中的行数来标识最新的报告。
这很好用,但是必须使用三个查询(一个加两个子查询)来完成这项工作很笨拙。这是正确的还是我不知道有什么技巧可以更优雅地做到这一点?
ROW_NUMBER() 可能是最简单的解决方案:
select f.*
from (select f.*,
row_number() over (partition by f.id, f.year order by f.date desc) as seqnum
from #foo f
where f.date <= @date
) f
where seqnum = 1;
这基本上与版本性能相同。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。