使用Calendar.Date创建虚拟数据

时间:2019-06-27 14:56:33

标签: sql sql-server

我正在尝试创建时间表表,使用Calendar.Date生成空的“单元格”。

查询:

select  c.Date, d.DriverId, d.RouteId, d.StartTime
FROM    Calendar c
left outer join
(
  select 'ABC' DriverId, 101 RouteId, cast('2019-08-26 08:30:00.000' as datetime) StartTime
  union all
  select 'ABC' DriverId, 101 RouteId, cast('2019-08-29 08:30:00.000' as datetime) StartTime
  union all
  select 'DEF' DriverId, 201 RouteId, cast('2019-08-27 11:30:00.000' as datetime) StartTime
) d ON d.StartTime >= c.Date AND d.StartTime < DATEADD(DAY, 1, c.Date)
WHERE   1=1
and     c.date between '08/26/19' and '08/29/19'

结果:

Date,DriverId,RouteId,StartTime
2019-08-26 00:00:00.000,ABC,101,2019-08-26 08:30:00.000
2019-08-27 00:00:00.000,DEF,201,2019-08-27 11:30:00.000
2019-08-28 00:00:00.000,,,
2019-08-29 00:00:00.000,ABC,101,2019-08-29 08:30:00.000

所需:

Date,DriverId,RouteId,StartTime
2019-08-26 00:00:00.000,ABC,101,2019-08-26 08:30:00.000
2019-08-26 00:00:00.000,DEF,,
2019-08-27 00:00:00.000,ABC,,
2019-08-27 00:00:00.000,DEF,201,2019-08-27 11:30:00.000
2019-08-28 00:00:00.000,ABC,,
2019-08-28 00:00:00.000,DEF,,
2019-08-29 00:00:00.000,ABC,101,2019-08-29 08:30:00.000
2019-08-29 00:00:00.000,DEF,,

一个CROSS JOIN

select  c.Date, d.DriverId, d.RouteId, d.StartTime
FROM    Calendar c
cross join
(
  select 'ABC' DriverId, 101 RouteId, cast('2019-08-26 08:30:00.000' as datetime) StartTime
  union all
  select 'ABC' DriverId, 101 RouteId, cast('2019-08-29 08:30:00.000' as datetime) StartTime
  union all
  select 'DEF' DriverId, 201 RouteId, cast('2019-08-27 11:30:00.000' as datetime) StartTime
) d 
WHERE   1=1
and     c.date between '08/26/19' and '08/29/19'

没有产生期望的结果:

Date,DriverId,RouteId,StartTime
2019-08-26 00:00:00.000,ABC,101,2019-08-26 08:30:00.000
2019-08-26 00:00:00.000,ABC,101,2019-08-29 08:30:00.000
2019-08-26 00:00:00.000,DEF,201,2019-08-27 11:30:00.000
2019-08-27 00:00:00.000,ABC,101,2019-08-26 08:30:00.000
2019-08-27 00:00:00.000,ABC,101,2019-08-29 08:30:00.000
2019-08-27 00:00:00.000,DEF,201,2019-08-27 11:30:00.000
2019-08-28 00:00:00.000,ABC,101,2019-08-26 08:30:00.000
2019-08-28 00:00:00.000,ABC,101,2019-08-29 08:30:00.000
2019-08-28 00:00:00.000,DEF,201,2019-08-27 11:30:00.000
2019-08-29 00:00:00.000,ABC,101,2019-08-26 08:30:00.000
2019-08-29 00:00:00.000,ABC,101,2019-08-29 08:30:00.000
2019-08-29 00:00:00.000,DEF,201,2019-08-27 11:30:00.000

是否有一种无需诉诸T/SQL就能获得结果的方法?

2 个答案:

答案 0 :(得分:1)

您似乎想要这样的东西:

select c.dte, d.DriverId, drs.RouteId, drs.StartTime
from (values ('ABC'), ('DEF')) d(DriverId) cross join
     (values (convert(date, '2019-08-26')), (convert(date, '2019-08-27')), (convert(date, '2019-08-28')), (convert(date, '2019-08-29'))
     ) c(dte) left join
     (values ('ABC', 101, cast('2019-08-26 08:30:00.000' as datetime)),
             ('ABC', 101, cast('2019-08-29 08:30:00.000' as datetime)),
             ('DEF', 201, cast('2019-08-27 11:30:00.000' as datetime)
     ) drs(DriverId, RouteId, StartTime)
     on drs.driverId = d.driverId and
        drs.StartTime >= c.dte and drs.StartTime < dateadd(day, 1, c.dte)
order by dte, driverid,

Here是db <>小提琴。

您可以使用日历表,但对于本示例,我认为不需要。

答案 1 :(得分:1)

看起来您可以交叉申请并获得最长的开始时间:

SELECT 
c.val, 
d.driverid, 
MAX(CASE WHEN c.val <> CAST(CAST(d.starttime AS DATE) AS DATETime) THEN NULL else d.routeid end) AS routeid,
MAX(CASE WHEN c.val <> CAST(CAST(d.starttime AS DATE) AS DATETime) THEN NULL else d.starttime end) AS start_time

FROM calendar c
CROSS APPLY driverstuff d

GROUP BY c.val, d.driverid
ORDER BY c.val