![](/img/trans.png)
[英]SQL Server 2012 T-SQL count number of words between elements of two sets
[英]Count Number of Intersections Between Two Date Ranges in T-SQL
我有以下兩個表(顯示了一些示例數據):
假日
Start | End
-----------|-----------
2000-01-01 | 2000-01-02
2000-02-20 | 2000-02-20
事件
Title | Date
-----------|-----------
Foo | 2000-01-03
Bar | 2000-01-20
如何返回Event.Date
前一周內發生的假日天數?
SELECT
e.Title,
e.Date,
DaysHolidayInPastWeek <-- How to get this?
FROM Event e
示例輸出
Title | Date | DaysHolidayInPastWeek
-----------|------------|----------------------
Foo | 2000-01-03 | 2
Bar | 2000-01-20 | 0
樣本數據
DECLARE @Holiday TABLE (HolidayStart date, HolidayEnd date);
INSERT INTO @Holiday (HolidayStart, HolidayEnd) VALUES
('2000-01-01', '2000-01-02'),
('2000-03-31', '2000-03-31'),
('2000-03-20', '2000-03-27'),
('2000-05-01', '2000-05-30');
DECLARE @Event TABLE (Title nvarchar(50), dt date);
INSERT INTO @Event (Title, dt) VALUES
('Foo', '2000-01-03'),
('Bar', '2000-01-20'),
('444', '2000-04-01'),
('555', '2000-05-10');
詢問
假設HolidayStart
和HolidayEnd
日期都包含在內。 CROSS APPLY E
只是為DATEADD
函數的結果創建了方便的別名,因此我可以稍后編寫簡短的EventStart
而不是長DATEADD
表達式。
OUTER APPLY
給出Holiday
中與給定Event的周相交的所有行的列表。 交叉持續時間從max of starts
到min of ends
。
主SELECT
組將所有交叉點匯總在一起。
SELECT
Ev.Title
,Ev.dt
,ISNULL(SUM(DATEDIFF(day,
Intersections.IntersectionStart,
Intersections.IntersectionEnd) + 1), 0) AS DaysHolidayInPastWeek
FROM
@Event AS Ev
CROSS APPLY
(
SELECT
DATEADD(day, -6, Ev.dt) AS EventStart
,Ev.dt AS EventEnd
) AS E
OUTER APPLY
(
SELECT
-- intersection duration is:
-- max of starts
-- min of ends
CASE WHEN E.EventStart > H.HolidayStart
THEN E.EventStart ELSE H.HolidayStart END AS IntersectionStart
,CASE WHEN E.EventEnd < H.HolidayEnd
THEN E.EventEnd ELSE H.HolidayEnd END AS IntersectionEnd
FROM @Holiday AS H
WHERE
-- two intervals intersect
H.HolidayEnd >= E.EventStart
AND H.HolidayStart <= E.EventEnd
) AS Intersections
GROUP BY
Ev.Title
,Ev.dt
;
結果
Title dt DaysHolidayInPastWeek
Foo 2000-01-03 2
Bar 2000-01-20 0
444 2000-04-01 3
555 2000-05-10 7
嘗試以下查詢。
SELECT
e.Title,
e.Date,
(
SELECT
SUM(DATEDIFF(DAY, h.start, h.end)) AS CountOfHoliday
FROM
Holiday h
WHERE
h.EventId = e.Id AND -- releation id
h.Start >= DATEADD(DAY, -7, e.date) AND
h.Start <= e.date -- Or delete this. Just h.Start >= DATEADD(DAY, -7, e.date)
) AS DaysHolidayInPastWeek
FROM
Event e
此查詢還管理事件日期屬於假日期間的情況。
SELECT Title, Date,
(
SELECT
sum(cntdays) from
(select start, [end],
case
when E.Date between start and [End]
then DATEDIFF(DAY, Start, E.Date)
when (
DATEADD(DAY, -7,E.Date) between start and [End]
or
DATEADD(DAY, -7,E.Date) < start
) and E.Date > start
then DATEDIFF(DAY, start, [end]) + 1
else 0
end as cntdays
from Holiday
) as H
) AS DaysHolidayInPastWeek
FROM Event AS E
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.