我需要一些关于在SQL上的频率列上为每个计数创建行的有效方法的想法。 (SQL Server 2016)
数据:
我有一张桌子上有人们生病的日期以及他们说他们将缺席多少天:
BEGIN_DATE DAYS_SICK
2011-01-01 00:00:00.000 3
2011-01-01 00:00:00.000 3
2011-01-01 00:00:00.000 1
2011-01-02 00:00:00.000 2
2011-01-02 00:00:00.000 3
2011-01-04 00:00:00.000 4
2011-01-04 00:00:00.000 4
2011-01-04 00:00:00.000 3
我想将其翻译成一个表格,其中每一行代表一年中的一天,我会计算那天生病的人数。
DATE PEOPLE_SICK
2011-01-01 00:00:00.000 3
2011-01-02 00:00:00.000 4
2011-01-03 00:00:00.000 4
2011-01-04 00:00:00.000 4
2011-01-05 00:00:00.000 3
2011-01-06 00:00:00.000 3
2011-01-07 00:00:00.000 2
例如:
我目前正在通过迭代输入中的每一行然后循环频率,根据需要在新表上添加或更新行来执行此操作,但这需要花费大量时间。
还有其他方法可以更有效地做到这一点吗?
答案 0 :(得分:1)
这根本不会与周末打交道,但可以帮助你入门。此外,如果有一个经常运行的查询,我会构建一个DATE DIM表并使用它而不是Dates CTE。 Where I got the DATE DIM code from.
CREATE TABLE #test (ID int IDENTITY(1,1), BEGIN_DATE datetime, DAYS_SICK int);
DECLARE @StartDate datetime = '2011-01-01'
, @CutoffDate datetime = '2011-01-10';
INSERT INTO #test (BEGIN_DATE, DAYS_SICK)
VALUES
('2011-01-01 00:00:00.000', 3),
('2011-01-01 00:00:00.000', 3),
('2011-01-01 00:00:00.000', 1),
('2011-01-02 00:00:00.000', 2),
('2011-01-02 00:00:00.000', 3),
('2011-01-04 00:00:00.000', 4),
('2011-01-04 00:00:00.000', 4),
('2011-01-04 00:00:00.000', 3);
WITH Dates
AS (SELECT d
FROM (
SELECT d = DATEADD(DAY, rn - 1, @StartDate)
FROM (SELECT TOP (DATEDIFF(DAY, @StartDate, @CutoffDate)) rn = ROW_NUMBER() OVER (
ORDER BY s1.[object_id])
FROM sys.all_objects AS s1
CROSS JOIN sys.all_objects AS s2
ORDER BY s1.[object_id]
) AS x
) AS y
)
,SickRanges
AS (
SELECT BEGIN_DATE
,DATEADD(DAY, DAYS_SICK - 1, BEGIN_DATE) END_DATE
FROM #test
)
SELECT d.d [DATE]
,count(1) PEOPLE_SICK
FROM SickRanges sr
JOIN Dates d ON d.d BETWEEN sr.BEGIN_DATE AND sr.END_DATE
GROUP BY d.d
ORDER BY d.d
DROP TABLE #test