根据包含开始和结束日期的当前表构建表

时间:2011-09-12 03:54:58

标签: sql sql-server

我已经看到了一些这样做的例子,但我似乎无法让它正常工作......

我有一张表如下

ID | FK | Location | StartDateTime | EndDateTime

这是一个逗留段表。 FK与父记录相关,ID与每个住宿段相关。我想将每个逗留段分成小时段。所以如下; 如果开始时间是10:23,那么第一条记录将是

1 | 254 | Loc1 | 10:23 | 10:59
1 | 254 | Loc1 | 11:00 | 11:59
1 | 254 | Loc1 | 12:00 | 12:45
2 | 254 | Loc2 | 12:45 | 12:50

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

可能有各种方法来解决这个问题,例如递归CTE(如果您使用'2005+版本),数字表,日历表(也可以被视为特殊案例编号表方法)。

以下示例使用名为master..spt_values的系统表作为普通的numbers table

WITH sampledata (ID, FK, Location, StartDateTime, EndDateTime) AS (
  SELECT 1, 254, 'Loc1', CAST('20110910 10:23' AS datetime), CAST('20110910 12:45' AS datetime) UNION ALL
  SELECT 2, 254, 'Loc2', CAST('20110910 12:45' AS datetime), CAST('20110910 12:50' AS datetime)
),
hourly AS (
  SELECT
    d.ID,
    d.FK,
    d.Location,
    d.StartDateTime,
    d.EndDateTime,
    HourlyStartDateTime =               DATEADD(HOUR, DATEDIFF(HOUR, 0, d.StartDateTime) + v.number,     0),
    HourlyEndDateTime = DATEADD(MS, -3, DATEADD(HOUR, DATEDIFF(HOUR, 0, d.StartDateTime) + v.number + 1, 0))
  FROM sampledata d
    INNER JOIN master..spt_values v ON v.type = 'P'
     AND v.number BETWEEN 0 AND DATEDIFF(HOUR, d.StartDateTime, d.EndDateTime)
)
SELECT
  ID,
  FK,
  Location,
  StartDateTime = CASE WHEN StartDateTime < HourlyStartDateTime THEN HourlyStartDateTime ELSE StartDateTime END,
  EndDateTime   = CASE WHEN EndDateTime   > HourlyEndDateTime   THEN HourlyEndDateTime   ELSE EndDateTime   END
FROM hourly

因为我不确定数据中的时间粒度,所以我将HourlyEndDateTime定义为“当前小时结束时的3毫秒”。您可以将其更改为“1秒 1分钟到小时结束”。