选择日期范围加入

时间:2017-05-17 21:09:24

标签: sql datetime sql-server-2008-r2 timespan date-range

我有一个查询在'01 / 05/2017'和'05 / 05/2017'之间选择并返回

之类的行
Date       EmployeeCode  EmployeeName  EntryTime   ExitTime
01/05/2017     10             a           08:00       18:00
02/05/2017     10             a           08:30       17:30
03/05/2017     10             a           08:30       17:30
03/05/2017     10             c           07:30       19:30
04/05/2017     10             c           09:30       18:30
05/05/2017     10             c           08:30       15:30

但我希望看到像

Date       EmployeeCode  EmployeeName  EntryTime   ExitTime
01/05/2017     10             a           08:00       18:00
02/05/2017     10             a           08:30       17:30
03/05/2017     10             a           08:30       17:30
04/05/2017     10             a             -          -
05/05/2017     10             a           08:30       17:30
01/05/2017     10             c             -          -
02/05/2017     10             c             -          -
03/05/2017     10             c           07:30       19:30
04/05/2017     10             c           09:30       18:30
05/05/2017     10             c           08:30       15:30
  

我尝试加入日期范围,但无法获得我想要的结果。

     WITH mycte AS
 (
  SELECT CAST('2017-05-01' AS DATETIME) DateValue
  UNION ALL
  SELECT  DateValue + 1
  FROM    mycte   
  WHERE   DateValue + 1 <= CAST('2017-05-05' AS DATETIME)
 )

 SELECT  
 DateValue
 FROM mycte 
  

如何获取此行?

1 个答案:

答案 0 :(得分:2)

您可以生成日期和cross join您的员工,然后left join到您的进入/退出时间表。

这使用堆叠的cte来生成日期:

declare @fromdate date = '20170401'
declare @thrudate date = '20170505'
;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]
)
select d.[Date], e.EmployeeCode, e.EmployeeName, t.EntryTime, t.ExitTime
from dates d
  cross join (
    select EmployeeCode, EmployeeName
    from Employees
    ) e
  left join TimeCard t
    on t.Date = d.Date
   and t.EmployeeCode = e.EmployeeCode

更好的是,您可以创建日期表。

对于内存中只有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]);

数字和日历表参考: