Return 如果不存在则每个时间增量一行
Return a row for each time increment if it does not exist
我有一个查询,returns 一年中每天每 15 分钟增量收到的工作量。问题是,如果在该时间范围内收到作业,则每 15 分钟增量中只有 returns 数据。查询的简洁版本是:
SELECT
DATEPART(MONTH, Datim) AS Month#,
DATEPART(DAY, Datim) AS Day#,
(DATEPART(HOUR, Datim) + 1) AS Hour#,
((DATEPART(MINUTE, Datim) / 15) + 1) AS Interval#,
COUNT(JobNumber) AS TotalJobs
FROM Table
WHERE (Datim >= '2020-01-01' AND Datim <= '2021-01-01')
GROUP BY
DATEPART(MONTH, Datim),
DATEPART(DAY, Datim),
(DATEPART(HOUR, Datim) + 1),
((DATEPART(MINUTE, Datim) / 15) + 1)
ORDER BY
DATEPART(MONTH, Datim),
(DATEPART(DAY, Datim) + 0),
(DATEPART(HOUR, Datim) + 1),
((DATEPART(MINUTE, Datim) / 15) + 1)
这是当前返回的输出:
Month#
Day#
Hour#
Interval#
TotalJobs
1
1
1
3
123
1
1
2
4
456
1
1
4
1
789
我希望数据输出为每个 15 分钟增量的 TotalJobs 字段填充 0,如果它们不存在,则填充小时。最终输出如下所示:
Month#
Day#
Hour#
Interval#
TotalJobs
1
1
1
1
0
1
1
1
2
0
1
1
1
3
123
1
1
1
4
0
1
1
2
1
0
1
1
2
2
0
1
1
2
3
0
1
1
2
4
456
1
1
3
1
0
1
1
3
2
0
1
1
3
3
0
1
1
3
4
0
1
1
4
1
789
1
1
4
2
0
1
1
4
3
0
1
1
4
4
0
关于实现此目标的最佳方法有什么想法吗?
可能的解决方案 tally table.
示例数据
将您当前的查询移动到子查询或公共 table 表达式 (CTE),以便您可以使用它进行左连接。在这里,我只是重新创建了您当前查询的结果行。
create table AvailableData
(
Month int,
Day int,
Hour int,
Interval int,
TotalJobs int
);
insert into AvailableData (Month, Day, Hour, Interval, TotalJobs) values
(1, 1, 1, 3, 123),
(1, 1, 2, 4, 456),
(1, 1, 4, 1, 789);
解决方案
为您提供 2021 年的前两个月。更新 CTE 的 Tally
和 Intervals
以获得更多增量数字和更多月份。
with Tally (n) as
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) a(n) -- 10^1 = 10
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) b(n) -- 10^2 = 100
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) c(n) -- 10^3 = 1000
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) d(n) -- 10^4 = 10000
),
Intervals as
(
select top (2*31*24*4) -- increase as required, max determined by Tally, example for 2 months
--t.n,
--dateadd(day, (t.n-1)/(24*4), '2021-01-01') as [Date],
datepart(month, dateadd(day, (t.n-1)/(24*4), '2021-01-01')) as [Month],
datepart(day, dateadd(day, (t.n-1)/(24*4), '2021-01-01')) as [Day],
(((t.n-1) % (24*4)))/4 +1 as [Hour],
( (t.n-1) % 4 ) +1 as [Interval]
from Tally t
)
select i.Month,
i.Day,
i.Hour,
i.Interval,
coalesce(ad.TotalJobs, 0) as TotalJobs
from Intervals i
left join AvailableData ad
on ad.Month = i.Month
and ad.Day = i.Day
and ad.Hour = i.Hour
and ad.Interval = i.Interval;
Fiddle 有一些中间结果。
完整解决方案
快速合并和编辑 2021 年全年。未验证。
with Tally (n) as
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM ( VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) a(n) -- 10^1 = 10
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) b(n) -- 10^2 = 100
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) c(n) -- 10^3 = 1000
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) d(n) -- 10^4 = 10000
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) e(n) -- 10^5 = 100000
),
Intervals as
(
select top (365*24*4) -- full year of 2021
datepart(month, dateadd(day, (t.n-1)/(24*4), '2021-01-01')) as [Month],
datepart(day, dateadd(day, (t.n-1)/(24*4), '2021-01-01')) as [Day],
(((t.n-1) % (24*4)))/4 +1 as [Hour],
( (t.n-1) % 4 ) +1 as [Interval]
from Tally t
),
AvailableData as
(
SELECT
DATEPART(MONTH, Datim) AS [Month],
DATEPART(DAY, Datim) AS [Day],
(DATEPART(HOUR, Datim) + 1) AS [Hour],
((DATEPART(MINUTE, Datim) / 15) + 1) AS [Interval],
COUNT(JobNumber) AS TotalJobs
FROM Table
WHERE (Datim >= '2020-01-01' AND Datim <= '2021-01-01')
GROUP BY
DATEPART(MONTH, Datim),
DATEPART(DAY, Datim),
(DATEPART(HOUR, Datim) + 1),
((DATEPART(MINUTE, Datim) / 15) + 1)
)
select i.Month,
i.Day,
i.Hour,
i.Interval,
coalesce(ad.TotalJobs, 0) as TotalJobs
from Intervals i
left join AvailableData ad
on ad.Month = i.Month
and ad.Day = i.Day
and ad.Hour = i.Hour
and ad.Interval = i.Interval
order by i.Month,
i.Day,
i.Hour,
i.Interval;
我有一个查询,returns 一年中每天每 15 分钟增量收到的工作量。问题是,如果在该时间范围内收到作业,则每 15 分钟增量中只有 returns 数据。查询的简洁版本是:
SELECT
DATEPART(MONTH, Datim) AS Month#,
DATEPART(DAY, Datim) AS Day#,
(DATEPART(HOUR, Datim) + 1) AS Hour#,
((DATEPART(MINUTE, Datim) / 15) + 1) AS Interval#,
COUNT(JobNumber) AS TotalJobs
FROM Table
WHERE (Datim >= '2020-01-01' AND Datim <= '2021-01-01')
GROUP BY
DATEPART(MONTH, Datim),
DATEPART(DAY, Datim),
(DATEPART(HOUR, Datim) + 1),
((DATEPART(MINUTE, Datim) / 15) + 1)
ORDER BY
DATEPART(MONTH, Datim),
(DATEPART(DAY, Datim) + 0),
(DATEPART(HOUR, Datim) + 1),
((DATEPART(MINUTE, Datim) / 15) + 1)
这是当前返回的输出:
Month# | Day# | Hour# | Interval# | TotalJobs |
---|---|---|---|---|
1 | 1 | 1 | 3 | 123 |
1 | 1 | 2 | 4 | 456 |
1 | 1 | 4 | 1 | 789 |
我希望数据输出为每个 15 分钟增量的 TotalJobs 字段填充 0,如果它们不存在,则填充小时。最终输出如下所示:
Month# | Day# | Hour# | Interval# | TotalJobs |
---|---|---|---|---|
1 | 1 | 1 | 1 | 0 |
1 | 1 | 1 | 2 | 0 |
1 | 1 | 1 | 3 | 123 |
1 | 1 | 1 | 4 | 0 |
1 | 1 | 2 | 1 | 0 |
1 | 1 | 2 | 2 | 0 |
1 | 1 | 2 | 3 | 0 |
1 | 1 | 2 | 4 | 456 |
1 | 1 | 3 | 1 | 0 |
1 | 1 | 3 | 2 | 0 |
1 | 1 | 3 | 3 | 0 |
1 | 1 | 3 | 4 | 0 |
1 | 1 | 4 | 1 | 789 |
1 | 1 | 4 | 2 | 0 |
1 | 1 | 4 | 3 | 0 |
1 | 1 | 4 | 4 | 0 |
关于实现此目标的最佳方法有什么想法吗?
可能的解决方案 tally table.
示例数据
将您当前的查询移动到子查询或公共 table 表达式 (CTE),以便您可以使用它进行左连接。在这里,我只是重新创建了您当前查询的结果行。
create table AvailableData
(
Month int,
Day int,
Hour int,
Interval int,
TotalJobs int
);
insert into AvailableData (Month, Day, Hour, Interval, TotalJobs) values
(1, 1, 1, 3, 123),
(1, 1, 2, 4, 456),
(1, 1, 4, 1, 789);
解决方案
为您提供 2021 年的前两个月。更新 CTE 的 Tally
和 Intervals
以获得更多增量数字和更多月份。
with Tally (n) as
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) a(n) -- 10^1 = 10
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) b(n) -- 10^2 = 100
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) c(n) -- 10^3 = 1000
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) d(n) -- 10^4 = 10000
),
Intervals as
(
select top (2*31*24*4) -- increase as required, max determined by Tally, example for 2 months
--t.n,
--dateadd(day, (t.n-1)/(24*4), '2021-01-01') as [Date],
datepart(month, dateadd(day, (t.n-1)/(24*4), '2021-01-01')) as [Month],
datepart(day, dateadd(day, (t.n-1)/(24*4), '2021-01-01')) as [Day],
(((t.n-1) % (24*4)))/4 +1 as [Hour],
( (t.n-1) % 4 ) +1 as [Interval]
from Tally t
)
select i.Month,
i.Day,
i.Hour,
i.Interval,
coalesce(ad.TotalJobs, 0) as TotalJobs
from Intervals i
left join AvailableData ad
on ad.Month = i.Month
and ad.Day = i.Day
and ad.Hour = i.Hour
and ad.Interval = i.Interval;
Fiddle 有一些中间结果。
完整解决方案
快速合并和编辑 2021 年全年。未验证。
with Tally (n) as
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM ( VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) a(n) -- 10^1 = 10
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) b(n) -- 10^2 = 100
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) c(n) -- 10^3 = 1000
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) d(n) -- 10^4 = 10000
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) e(n) -- 10^5 = 100000
),
Intervals as
(
select top (365*24*4) -- full year of 2021
datepart(month, dateadd(day, (t.n-1)/(24*4), '2021-01-01')) as [Month],
datepart(day, dateadd(day, (t.n-1)/(24*4), '2021-01-01')) as [Day],
(((t.n-1) % (24*4)))/4 +1 as [Hour],
( (t.n-1) % 4 ) +1 as [Interval]
from Tally t
),
AvailableData as
(
SELECT
DATEPART(MONTH, Datim) AS [Month],
DATEPART(DAY, Datim) AS [Day],
(DATEPART(HOUR, Datim) + 1) AS [Hour],
((DATEPART(MINUTE, Datim) / 15) + 1) AS [Interval],
COUNT(JobNumber) AS TotalJobs
FROM Table
WHERE (Datim >= '2020-01-01' AND Datim <= '2021-01-01')
GROUP BY
DATEPART(MONTH, Datim),
DATEPART(DAY, Datim),
(DATEPART(HOUR, Datim) + 1),
((DATEPART(MINUTE, Datim) / 15) + 1)
)
select i.Month,
i.Day,
i.Hour,
i.Interval,
coalesce(ad.TotalJobs, 0) as TotalJobs
from Intervals i
left join AvailableData ad
on ad.Month = i.Month
and ad.Day = i.Day
and ad.Hour = i.Hour
and ad.Interval = i.Interval
order by i.Month,
i.Day,
i.Hour,
i.Interval;