如何推断 SQL Server 中的日期以计算每日计数?
Posted
技术标签:
【中文标题】如何推断 SQL Server 中的日期以计算每日计数?【英文标题】:How to extrapolate dates in SQL Server to calculate the daily counts? 【发布时间】:2021-11-23 19:56:48 【问题描述】:这就是数据的样子。这是一张长桌
我需要计算每天雇用的人数
如何编写 SQL Server 逻辑来得到这个结果?我想创建一个 DATES 表然后加入,但这会导致错误,因为表太大。我需要递归逻辑吗?
【问题讨论】:
根据问题指南,请不要发布代码、数据、错误消息等的图像 - 将文本复制或输入到问题中。请保留将图像用于图表或演示渲染错误,无法通过文本准确描述的事情。 根据问题指南,请展示您的尝试并告诉我们您发现了什么(在本网站或其他地方)以及为什么它不能满足您的需求。 你遇到了什么错误?日历表应该可以完美运行。 以下任何答案对您有帮助吗? 【参考方案1】:对于未来的问题,请勿发布数据图片。相反,请使用dbfiddle 之类的服务。无论如何,我会为答案添加一个草图,如果你有一个准备得更好的问题,你可能会得到一个完整的答案。无论如何它都在这里:
-- extrema is the least and the greatest date in staff table
with extrema(mn, mx) as (
select least(min(hired),min(retired)) as mn
, greatest(max(hired),max(retired)) as mx
from staff
), calendar (dt) as (
-- we construct a calendar with every date between extreme values
select mn from extrema
union all
select dateadd(day, 1, d)
from calendar
where dt < (select mx from extrema)
)
-- finally we can count the number of employed people for each such date
select dt, count(1)
from calendar c
join staff s
on c.dt between s.hired and s.retired
group by dt;
如果您发现自己经常进行此类计算,最好创建一个日历表。您可以为其添加其他属性,例如它是否是一周中的某一天等。
约束为:
CHECK(hired <= retired)
第一部分可以简化为:
with extrema(mn, mx) as (
select min(hired) as mn
, max(retired) as mx
from staff
),
【讨论】:
【参考方案2】:假设当前员工的退休日期为 NULL
Declare @Date1 date = '2015-01-01'
Declare @Date2 date = getdate()
Select A.Date
,HeadCount = count(B.name)
From ( Select Top (DateDiff(DAY,@Date1,@Date2)+1)
Date=DateAdd(DAY,-1+Row_Number() Over (Order By (Select Null)),@Date1)
From master..spt_values n1,master..spt_values n2
) A
Left Join YourTable B on A.Date >= B.Hired and A.Date <= coalesce(B.Retired,getdate())
Group BY A.Date
【讨论】:
【参考方案3】:为此您需要一个日历表。您从日历开始,然后使用BETWEEN
逻辑左连接其他所有内容。
您可以使用真实的桌子。或者您可以即时生成它,如下所示:
WITH
L0 AS ( SELECT c = 1
FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),
(1),(1),(1),(1),(1),(1),(1),(1)) AS D(c) ),
L1 AS ( SELECT c = 1 FROM L0 A, L0 B, L0 C, L0 D ),
Nums AS ( SELECT rownum = ROW_NUMBER() OVER(ORDER BY (SELECT 1))
FROM L1 ),
Dates AS (
SELECT TOP (DATEDIFF(day, '20141231', GETDATE()))
Date = DATEADD(day, rownum, '20141231')
FROM Nums
)
SELECT
d.Date,
NumEmployed = COUNT(*)
FROM Dates d
JOIN YourTable t ON d.Date BETWEEN t.Hired AND t.Retired
GROUP BY
d.Date;
如果您的日期有时间组件,那么您需要使用 >= AND <
逻辑
【讨论】:
【参考方案4】:尝试限制日期表的范围。在此示例中,我有一个名为 TallyStickDT 的日期表。
SELECT dt, COUNT(name)
FROM (
SELECT dt
FROM tallystickdt
WHERE dt >= (SELECT MIN(hired) FROM #employees)
AND dt <= GETDATE()
) A
LEFT OUTER JOIN #employees E ON A.dt >= E.Hired AND A.dt <= e.retired
GROUP BY dt
ORDER BY dt
【讨论】:
以上是关于如何推断 SQL Server 中的日期以计算每日计数?的主要内容,如果未能解决你的问题,请参考以下文章