如果你想在 SQL 中解决这个问题,那么你可以使用日历或日期表来处理这类事情。
对于只有 152kb 的内存,您可以在一个表中包含 30 年的日期:
/* dates table */
declare @fromdate date = '20000101';
declare @years int = 30;
/* 30 years, 19 used data pages ~152kb in memory, ~264kb on disk */
;with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
select top (datediff(day, @fromdate,dateadd(year,@years,@fromdate)))
[Date]=convert(date,dateadd(day,row_number() over(order by (select 1))-1,@fromdate))
into dbo.Dates
from n as deka cross join n as hecto cross join n as kilo
cross join n as tenK cross join n as hundredK
order by [Date];
create unique clustered index ix_dbo_Dates_date on dbo.Dates([Date]);
无需执行创建表的实际步骤,您就可以使用 common table expression 生成一个临时的日期表,只需这样做:
declare @fromdate date, @thrudate date;
select @fromdate = min(fromdate), @thrudate = max(thrudate) from dbo.leave;
;with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
, dates as (
select top (datediff(day, @fromdate, @thrudate)+1)
[Date]=convert(date,dateadd(day,row_number() over(order by (select 1))-1,@fromdate))
from n as deka cross join n as hecto cross join n as kilo
cross join n as tenK cross join n as hundredK
order by [Date]
)
像这样使用:
/* `distinct` if there are overlaps or duplicates to remove */
select distinct
l.personid
, d.[Date]
from dbo.leave l
inner join dates d
on d.date >= l.fromdate
and d.date <= l.thrudate;
rextester 演示:http://rextester.com/AVOIN59493
来自这个测试数据:
create table leave (personid int, fromdate date, thrudate date)
insert into leave values
(1,'20170101','20170107')
,(1,'20170104','20170106') -- overlapped
,(1,'20170420','20170422')
,(2,'20170207','20170207') -- single day
,(2,'20170330','20170405')
返回:
+----------+------------+
| personid | Date |
+----------+------------+
| 1 | 2017-01-01 |
| 1 | 2017-01-02 |
| 1 | 2017-01-03 |
| 1 | 2017-01-04 |
| 1 | 2017-01-05 |
| 1 | 2017-01-06 |
| 1 | 2017-01-07 |
| 1 | 2017-04-20 |
| 1 | 2017-04-21 |
| 1 | 2017-04-22 |
| 2 | 2017-02-07 |
| 2 | 2017-03-30 |
| 2 | 2017-03-31 |
| 2 | 2017-04-01 |
| 2 | 2017-04-02 |
| 2 | 2017-04-03 |
| 2 | 2017-04-04 |
| 2 | 2017-04-05 |
+----------+------------+
数字和日历表参考: