下面是一些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
瑞恩 - 請查看更新的描述,讓我知道,如果這有助於。謝謝! –
你試過我的解決方案嗎? – Shago