我遇到以下问题:我有两个表
Article
id state
Guid int
和
Article_history
id state datechange
Guid int datetime
第一个表存储产品信息,第二个表填充,然后产品状态发生更改。例如
Article
id state
1 1
Article_history
id state datechange
1 1 2019-11-10
1 2 2020-01-15
我需要为几年内的每一篇文章创建一份报告,步长为一个月:
date id state
2019-11-01 1 1
2019-12-01 1 1 --There is my problem
2020-01-01 1 2
我创建了对Article_history
表的查询,但由于我的应用程序仅在更改文章状态
时创建记录,因此并非每个月都会在Article_history
中显示。在我的示例中,我实际上没有 2019-12-01 的记录。我需要用最后已知的状态来填补每个产品的时间间隙。
我无法想象在给定期间的每个月不使用光标的情况下填补这一空白的方法,但这需要很多时间。 请给我建议。
模拟
Create TABLE Article
(
id int,
state int
)
Create TABLE Article_history
(
id int,
datechange datetime,
state int
)
Insert into Article (id, state)
VALUES (1,1)
,(2,1)
,(3,2)
INSERT into Article_history (id, datechange, state)
VALUES (1,'2019-11-10',1)
,(1,'2020-01-15',2);
我的查询:
With theDates As
(
Select DATEFROMPARTS(2019,11,1) as theDate
Union All
Select DateAdd(MONTH,1,theDate)
From theDates
Where DATEADD(MONTH,1,theDate)<=GETDATE()
)
Select
Convert(date,dt.theDate,104) as 'date'
,arth.id
,arth.state
From theDates as dt
left join Article_history as arth
on arth.datechange>=DATEADD(month, DATEDIFF(month, 0, dt.theDate), 0) and arth.datechange<=EOMONTH(dt.theDate)
Option (Maxrecursion 0)
我的结果:
date id state
2019-11-01 1 1
2020-01-01 1 2
我想要得到
date id state
2019-11-01 1 1
2019-12-01 1 1
2020-01-01 1 2
十二月不见了
为了澄清我的问题:来自 Article
的记录可能根本不在 Article_history
中,如果是这样,我想将此记录放入每个月并带有一些默认值。
UPD:Article
表有大约 3k 条记录。 Article
中的 PR id 是 Article_history
的 FK。我需要为 Article
中的每条记录创建一个表示。在伪代码中:
foreach article in Article {
foreach month in TheDates {
if(article.id not in result where result.month = month) {
AddInResult(new [result.month=month, result.id=article.id, result.state = GetLastStateFromArticleHistory(article.id,month)]
}
}}
我有一个包含历史记录的结果表,但并未代表每个月的所有文章
。我需要添加此记录以及来自 Article_history
的最后可用状态。
最佳答案
首先,在提供最小示例和创建脚本方面做得很好。 另外,已经构建了所需的计数表,这很好——有很多方法,cte 就可以了。
现在,你的结果与我的不匹配。我得到了第三列,其中 id 和状态为 12 月的 NULL。也许您实际上运行了内部联接?
With theDates As
(
Select DATEFROMPARTS(2019,11,1) as theDate
Union All
Select DateAdd(MONTH,1,theDate)
From theDates
Where DATEADD(MONTH,1,theDate)<=GETDATE()
)
Select
Convert(date,dt.theDate,104) as 'date'
,a.id
,lastone.*
From theDates as dt
cross join Article a -- cartesian product of dates * articles
outer apply
(
select top 1 state
from Article_history as arth
where
arth.datechange<EOMONTH(dt.theDate)
and a.id=arth.id
order by arth.datechange desc
) as lastone
order by id,dt.theDate
Result:
+------------+----+-------+
| date | id | state |
+------------+----+-------+
| 2019-11-01 | 1 | 1 |
| 2019-12-01 | 1 | 1 |
| 2020-01-01 | 1 | 2 |
| 2019-11-01 | 2 | NULL |
| 2019-12-01 | 2 | NULL |
| 2020-01-01 | 2 | NULL |
| 2019-11-01 | 3 | NULL |
| 2019-12-01 | 3 | NULL |
| 2020-01-01 | 3 | NULL |
+------------+----+-------+
关于sql-server - 将缺失记录添加到结果表记录中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59985681/