[英]Count Number of Intersections Between Two Date Ranges in T-SQL
I have the following two tables (some sample data shown): 我有以下两个表(显示了一些示例数据):
Holiday 假日
Start | End
-----------|-----------
2000-01-01 | 2000-01-02
2000-02-20 | 2000-02-20
Event 事件
Title | Date
-----------|-----------
Foo | 2000-01-03
Bar | 2000-01-20
How can I return all events with the number of holiday days that have occurred during a week before Event.Date
? 如何返回
Event.Date
前一周内发生的假日天数?
SELECT
e.Title,
e.Date,
DaysHolidayInPastWeek <-- How to get this?
FROM Event e
Example Output 示例输出
Title | Date | DaysHolidayInPastWeek
-----------|------------|----------------------
Foo | 2000-01-03 | 2
Bar | 2000-01-20 | 0
Sample data 样本数据
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');
Query 询问
Assumes that HolidayStart
and HolidayEnd
dates are both inclusive. 假设
HolidayStart
和HolidayEnd
日期都包含在内。 CROSS APPLY E
is just to create handy alias for the result of the DATEADD
function, so that I could write short EventStart
later instead of the long DATEADD
expression. CROSS APPLY E
只是为DATEADD
函数的结果创建了方便的别名,因此我可以稍后编写简短的EventStart
而不是长DATEADD
表达式。
OUTER APPLY
gives a list of all rows in the Holiday
that intersect with the week of the given Event. OUTER APPLY
给出Holiday
中与给定Event的周相交的所有行的列表。 Intersection duration is from max of starts
till min of ends
. 交叉持续时间从
max of starts
到min of ends
。
Main SELECT
groups and sums all intersections together. 主
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
;
Result 结果
Title dt DaysHolidayInPastWeek
Foo 2000-01-03 2
Bar 2000-01-20 0
444 2000-04-01 3
555 2000-05-10 7
Try following query. 尝试以下查询。
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
this query also manages cases in which event date falls into a holiday period. 此查询还管理事件日期属于假日期间的情况。
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.