SQL 加入以填充缺失值
SQL join for filling missing values
我有一个table的历史数据(#Records);在存储过程结束时,我需要根据 table 日期 (dbo.MasterDates
) 填充数据。对于下面的简化示例,我将简单地使用 City 作为唯一数据系列的标识符。
tempdb.dbo.#记录:
日期
城市
价值
2021-06-04
洛杉矶
10.5
2021-06-04
纽约
11.2
2021-06-05
洛杉矶
9.2
2021-06-06
纽约
8.1
dbo.Dates:
日期
年份
月份
天
2021-06-04
2021
6
4
2021-06-05
2021
6
5
2021-06-06
2021
6
6
如果数据被过滤,因此只有一个系列被检索 (即,只有纽约市的数据),填充将是一个简单的 select 来自 dbo.Dates 和 #Records 上的 left outer join
。但是,我需要填写每个城市的每一天的记录。
例如(已填记录 加粗)
日期
城市
价值
2021-06-04
洛杉矶
10.5
2021-06-04
纽约
11.2
2021-06-05
洛杉矶
9.2
2021-06-05
纽约市
0.0
2021-06-06
LA
0.0
2021-06-06
纽约
8.1
我的第一次尝试是创建一个版本的 dbo.Dates,其中包含每个独特城市的记录,然后用它来填充 #记录 table:
insert into #FilledDates (Date, City)
select
dates.Date, City
from Dates d
cross apply
(
select distinct City from #Records
) r
select
d.Date, d.City, isnull(r.Value, 0)
from #FilledDates d
left outer join #Records r on r.Date = d.Date and r.City = d.City
这很好用;然而,考虑到实际用例要复杂得多,我很好奇是否有更好的方法来达到预期的结果。性能是我主要关心的问题...似乎我应该能够结合交叉应用和连接步骤,但是我对交叉应用还是有点陌生。
创建一个包含所有可能 city/date 组合的投影,然后加入:
WITH Projection AS (
SELECT City, [Date]
FROM Dates
CROSS JOIN (SELECT DISTINCT City FROM Records) c
)
SELECT p.*, coalesce(r.[Value], 0.0) as [Value]
FROM Projection p
LEFT JOIN #Records r ON r.[Date] = p.[Date] AND r.City = p.City
ORDER BY [Date], City
在这里查看它的工作原理:
我有一个table的历史数据(#Records);在存储过程结束时,我需要根据 table 日期 (dbo.MasterDates
) 填充数据。对于下面的简化示例,我将简单地使用 City 作为唯一数据系列的标识符。
tempdb.dbo.#记录:
日期 | 城市 | 价值 |
---|---|---|
2021-06-04 | 洛杉矶 | 10.5 |
2021-06-04 | 纽约 | 11.2 |
2021-06-05 | 洛杉矶 | 9.2 |
2021-06-06 | 纽约 | 8.1 |
dbo.Dates:
日期 | 年份 | 月份 | 天 |
---|---|---|---|
2021-06-04 | 2021 | 6 | 4 |
2021-06-05 | 2021 | 6 | 5 |
2021-06-06 | 2021 | 6 | 6 |
如果数据被过滤,因此只有一个系列被检索 (即,只有纽约市的数据),填充将是一个简单的 select 来自 dbo.Dates 和 #Records 上的 left outer join
。但是,我需要填写每个城市的每一天的记录。
例如(已填记录 加粗)
日期 | 城市 | 价值 |
---|---|---|
2021-06-04 | 洛杉矶 | 10.5 |
2021-06-04 | 纽约 | 11.2 |
2021-06-05 | 洛杉矶 | 9.2 |
2021-06-05 | 纽约市 | 0.0 |
2021-06-06 | LA | 0.0 |
2021-06-06 | 纽约 | 8.1 |
我的第一次尝试是创建一个版本的 dbo.Dates,其中包含每个独特城市的记录,然后用它来填充 #记录 table:
insert into #FilledDates (Date, City)
select
dates.Date, City
from Dates d
cross apply
(
select distinct City from #Records
) r
select
d.Date, d.City, isnull(r.Value, 0)
from #FilledDates d
left outer join #Records r on r.Date = d.Date and r.City = d.City
这很好用;然而,考虑到实际用例要复杂得多,我很好奇是否有更好的方法来达到预期的结果。性能是我主要关心的问题...似乎我应该能够结合交叉应用和连接步骤,但是我对交叉应用还是有点陌生。
创建一个包含所有可能 city/date 组合的投影,然后加入:
WITH Projection AS (
SELECT City, [Date]
FROM Dates
CROSS JOIN (SELECT DISTINCT City FROM Records) c
)
SELECT p.*, coalesce(r.[Value], 0.0) as [Value]
FROM Projection p
LEFT JOIN #Records r ON r.[Date] = p.[Date] AND r.City = p.City
ORDER BY [Date], City
在这里查看它的工作原理: