【问题标题】:Select Date Range Join选择日期范围加入
【发布时间】:2017-05-17 21:09:23
【问题描述】:

我有一个查询,它在 '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 

我怎样才能得到这些行?

【问题讨论】:

  • 您的数据库中有dates 表吗?
  • 这些是您正在寻找的日期吗? xkcd PSA ISO 8601
  • 加入日历表...有 100 个示例。
  • 我没有日期表@vkp。但我可以添加。
  • 日期是一个例子。我将发送日期参数@SqlZim

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


【解决方案1】:

您可以生成日期和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]);

数字和日历表参考:

【讨论】:

  • 你的答案并不完全是我想要的,但大部分是。你指导了我。谢谢。
  • @serdar 乐于助人!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-23
相关资源
最近更新 更多