【问题标题】:Calculating Timestamp Overlap Duration计算时间戳重叠持续时间
【发布时间】:2016-06-15 19:55:50
【问题描述】:

我有一家出租一种特定产品的公司。我想知道特定位置缺货的持续时间(以分钟为单位)。

第一个数据集具有包含位置 ID、租赁开始时间戳和租赁结束时间戳的交易历史记录。

第二个数据集包含位置 ID、日期和当天可供出租的单位数量。随着频繁添加/删除单位,单位数量可能每天都在变化。

我需要计算每个地点每天出租所有可用单位的分钟数。

例如:位置 A 在 2016 年 2 月 1 日有 3 个单位。 2016 年 2 月 1 日有多少分钟(如果有)同时出租 3 个单位?

SQL 是我需要使用的语言。

请参阅下面的示例数据集 Y:

LOC_ID, ACT_RNTL_BGN_TS, ACT_RNTL_END_TS

A   30Jan2016 19:54:37.000  01Feb2016 10:00:24.053

A   31Jan2016 16:30:23.000  01Feb2016 9:07:06.588

A   01Feb2016 9:22:22.000   02Feb2016 10:00:23.716

A   01Feb2016 9:36:11.000   01Feb2016 11:05:34.249

A   01Feb2016 10:27:34.000  01Feb2016 12:59:29.883

A   01Feb2016 10:40:38.000  01Feb2016 15:36:27.119

A   01Feb2016 12:43:10.000  01Feb2016 14:23:15.914

A   01Feb2016 13:28:20.000  01Feb2016 14:40:15.573

A   01Feb2016 17:03:13.000  01Feb2016 19:02:57.413

A   01Feb2016 17:17:12.000  01Feb2016 18:54:14.708

样本数据集Z如下:

LOC_ID, Date, Unit_Count

A 01Feb2016 3

A 02Feb2016 4

A 03Feb2016 3

B 01Feb2016 2

B 02Feb2016 2

B 03Feb2016 2

由于位置 A 在 2 月 1 日共有 3 个单元,因此所需的输出将是 25 分钟,这是 2 月 1 日在位置 A 同时出租 3 个单元的总时间。上午 10:40 之间和上午 11:05 3 个单位同时出租。

【问题讨论】:

  • Ryan - 请查看更新后的说明,如果有帮助,请告诉我。谢谢!
  • 你试过我的解决方案了吗?

标签: sql timestamp overlap duration


【解决方案1】:

这是一些 T-SQL 代码(您没有指出您使用的是哪个 DBMS)

-- DECLARING SAMPLE DATA
DECLARE @Z table (LOC_ID char, Date date, Unit_Count int)

INSERT @Z ( LOC_ID, Date, Unit_Count ) VALUES  ( 'A', '2016-02-01', 3)
INSERT @Z ( LOC_ID, Date, Unit_Count ) VALUES  ( 'A', '2016-02-02', 4)
INSERT @Z ( LOC_ID, Date, Unit_Count ) VALUES  ( 'A', '2016-02-03', 3)
INSERT @Z ( LOC_ID, Date, Unit_Count ) VALUES  ( 'B', '2016-02-01', 2)
INSERT @Z ( LOC_ID, Date, Unit_Count ) VALUES  ( 'B', '2016-02-02', 2)
INSERT @Z ( LOC_ID, Date, Unit_Count ) VALUES  ( 'B', '2016-02-03', 2)

DECLARE @Y table (LOC_ID char, ACT_RNTL_BGN_TS datetime, ACT_RNTL_END_TS datetime)

INSERT @Y ( LOC_ID, ACT_RNTL_BGN_TS, ACT_RNTL_END_TS ) VALUES ('A', '2016-01-30 19:54:37.000', '2016-02-01 10:00:24.053')
INSERT @Y ( LOC_ID, ACT_RNTL_BGN_TS, ACT_RNTL_END_TS ) VALUES ('A', '2016-01-31 16:30:23.000', '2016-02-01 09:07:06.588')
INSERT @Y ( LOC_ID, ACT_RNTL_BGN_TS, ACT_RNTL_END_TS ) VALUES ('A', '2016-02-01 09:22:22.000', '2016-02-02 10:00:23.716')
INSERT @Y ( LOC_ID, ACT_RNTL_BGN_TS, ACT_RNTL_END_TS ) VALUES ('A', '2016-02-01 09:36:11.000', '2016-02-01 11:05:34.249')
INSERT @Y ( LOC_ID, ACT_RNTL_BGN_TS, ACT_RNTL_END_TS ) VALUES ('A', '2016-02-01 10:27:34.000', '2016-02-01 12:59:29.883')
INSERT @Y ( LOC_ID, ACT_RNTL_BGN_TS, ACT_RNTL_END_TS ) VALUES ('A', '2016-02-01 10:40:38.000', '2016-02-01 15:36:27.119')
INSERT @Y ( LOC_ID, ACT_RNTL_BGN_TS, ACT_RNTL_END_TS ) VALUES ('A', '2016-02-01 12:43:10.000', '2016-02-01 14:23:15.914')
INSERT @Y ( LOC_ID, ACT_RNTL_BGN_TS, ACT_RNTL_END_TS ) VALUES ('A', '2016-02-01 13:28:20.000', '2016-02-01 14:40:15.573')
INSERT @Y ( LOC_ID, ACT_RNTL_BGN_TS, ACT_RNTL_END_TS ) VALUES ('A', '2016-02-01 17:03:13.000', '2016-02-01 19:02:57.413')
INSERT @Y ( LOC_ID, ACT_RNTL_BGN_TS, ACT_RNTL_END_TS ) VALUES ('A', '2016-02-01 17:17:12.000', '2016-02-01 18:54:14.708')
;

-- START OF QUERY
WITH SplittedRentedIntervals AS ( -- Intervals that span more than one day are splited.
    SELECT Z.LOC_ID
         , Z.Date
         , BGN = CASE WHEN Y.ACT_RNTL_BGN_TS > CAST(Z.Date AS datetime) THEN Y.ACT_RNTL_BGN_TS ELSE CAST(Z.Date AS datetime) END
         , [END] = CASE WHEN Y.ACT_RNTL_END_TS < CAST(DATEADD(DAY, 1, Z.Date) AS datetime) THEN Y.ACT_RNTL_END_TS ELSE CAST(DATEADD(DAY, 1, Z.Date) AS datetime) END
    FROM @Z Z
    JOIN @Y Y
    ON Y.LOC_ID = Z.LOC_ID
    AND (Z.Date = CAST(Y.ACT_RNTL_BGN_TS AS date)
      OR Z.Date = CAST(Y.ACT_RNTL_END_TS AS date)
      OR (Z.Date BETWEEN Y.ACT_RNTL_BGN_TS AND Y.ACT_RNTL_END_TS))
), Times AS ( -- All times starting and ending any interval, including start and end of day.
          SELECT DISTINCT LOC_ID, Date, TIME = BGN FROM SplittedRentedIntervals
    UNION SELECT DISTINCT LOC_ID, Date, TIME = [END] FROM SplittedRentedIntervals
    UNION SELECT LOC_ID, Date, TIME = CAST(Date AS datetime) FROM @Z
    UNION SELECT LOC_ID, Date, TIME = CAST(DATEADD(DAY, 1, Date) AS datetime) FROM @Z
), OrderedTimes AS (
    SELECT LOC_ID
         , Date
         , TIME
         , NUM = ROW_NUMBER() OVER (PARTITION BY LOC_ID, Date ORDER BY TIME ASC)
    FROM Times
), Intervals AS ( -- Intervals are conformed by two consecutives times.
    SELECT OT1.LOC_ID
         , OT1.Date
         , BGN = OT1.TIME
         , [END] = OT2.TIME
    FROM OrderedTimes OT1
    JOIN OrderedTimes OT2
    ON OT2.LOC_ID = OT1.LOC_ID
    AND OT2.Date = OT1.Date
    AND OT2.NUM = OT1.NUM + 1
), StockByInterval AS ( -- Intersect all time intervals with rented intervals to calculate rented units.
    SELECT I.LOC_ID
         , I.Date
         , I.BGN
         , I.[END]
         , STOCK = Z.Unit_Count
                 - (SELECT COUNT(*)
                    FROM SplittedRentedIntervals SRI
                    WHERE I.Date = SRI.Date
                    AND I.LOC_ID = SRI.LOC_ID
                    AND SRI.BGN < I.[END]
                    AND SRI.[END] > I.BGN)
    FROM Intervals I
    JOIN @Z Z
    ON Z.Date = I.Date
    AND Z.LOC_ID = I.LOC_ID
), WithuotStock AS ( -- Sum the minutes of intervals where there is no stock.
    SELECT LOC_ID
         , Date
         , MinutesWithoutStock = SUM(DATEDIFF(MINUTE, BGN, [END]))
    FROM StockByInterval
    WHERE STOCK <= 0 -- Sample data has some intervals where there are more items rented than are available.
    GROUP BY LOC_ID, Date
)
SELECT Z.LOC_ID
     , Z.Date
     , MinutesWithoutStock = ISNULL(WS.MinutesWithoutStock, 0)
FROM @Z Z
LEFT JOIN WithuotStock WS
ON WS.Date = Z.Date
AND WS.LOC_ID = Z.LOC_ID
ORDER BY Z.LOC_ID, Z.Date

样本输出

LOC_ID Date       MinutesWithoutStock
------ ---------- -------------------
A      2016-02-01 374
A      2016-02-02 0
A      2016-02-03 0
B      2016-02-01 0
B      2016-02-02 0
B      2016-02-03 0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-17
    相关资源
    最近更新 更多