2017-03-23 106 views
18

背景:獲取兩個時間之間的區別對於SQL Server 2012

我試圖確定的時間長度的客戶在特定的房間花費。每個客戶都可以通過CustomerID進行識別,當他們訪問時,他們被分配VisitNumber。例如,如果客戶今天參觀他們會得到的VisitNumber說:111111然後,他們將離開,回來下週將有一個111112.的VisitNumber

當客戶首次訪問他們不是最初分配的房間,並且當他們最終被分配到他們的指定房間時,一個條目被寫入數據庫。 CurrentRoom將是空白的,因爲他們還沒有房間,而NewRoom是他們已經搬進來的房間。

此項目將被記錄爲事件1(客戶從沒有空間的房間移動),時間是當交易發生。如果客戶將在現有住宿期間被移走,並將記錄爲事件9(客戶從一個房間移動到另一個房間),並且還將記錄該值。

我已成功使用LAG獲得上一行,並從下一行的時間的時間的問題LEAD,然後制定出之間的區別兩次,這給了我的時間長度,客戶在特定的房間裏度過的時間。

問題使用LAG是它獲得以前的值,在某些情況下可能是從一個完全不同的客戶價值時。我想獲得的LAG & LEAD值僅適用於特定CustomerID &當前VisitNumber然後制定出的值之間的差異,找出客戶在一個房間裏多長時間度過的。

演示數據:

CREATE TABLE #beds 
(
    [id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY, 
    [User] [nvarchar](50) NULL, 
    [CustomerID] [nvarchar](50) NULL, 
    [Area] [nchar](10) NULL, 
    [Event] [nvarchar](50) NULL, 
    [VisitNumber] [nvarchar](50) NULL, 
    [Time] [datetime] NULL, 
    [CurrentRoom] [nvarchar](50) NULL, 
    [NewRoom] [nvarchar](50) NULL 
) 
GO 

INSERT INTO #beds ([User],[CustomerID],[Area],[Event],[VisitNumber],[Time],[CurrentRoom],[NewRoom]) 
VALUES ('00001','C11111111','Area1',2,111111111,'2017-03-22 11:05:44.360','B22','B44'), 
('00001','C11111111','Area1',1,111111111,'2017-03-22 11:05:15.517','','B22'), 
('00001','C22222222','Area2',1,222222222,'2017-03-22 07:38:16.117','','POD3'), 
('00001','C22222222','Area2',3,222222222,'2017-03-22 07:41:24.787','POD3','POD3'), 
('00001','C22222222','Area2',9,222222222,'2017-03-22 09:10:49.697','POD3',''), 
('00001','C22222222','Area2',1,222222222,'2017-03-22 10:05:19.130','','POD15'), 
('00001','C22222222','Area2',2,222222222,'2017-03-22 10:13:43.057','POD15','A'), 
('00001','C22222222','Area2',3,222222222,'2017-03-22 10:25:01.527','A','A'), 
('00001','C22222222','Area2',3,222222222,'2017-03-22 10:46:03.960','A','A'), 
('00001','C22222222','Area2',3,222222222,'2017-03-22 10:46:17.030','A','A'), 
('00002','C33333333','Area3',1,333333333,'2017-03-22 09:20:23.660','','B46'), 
('00001','C33333333','Area2',9,333333333,'2017-03-22 08:53:32.860','POD8','POD1'), 
('00001','C33333333','Area2',1,333333333,'2017-03-22 07:34:58.810','POD7','POD8'), 
('00001','C33333333','Area2',1,333333333,'2017-03-22 11:49:55.203','','BB4'), 
('00001','C33333333','Area2',3,333333333,'2017-03-22 11:50:11.943','BB4','BB4'), 
('00001','C33333333','Area2',3,333333333,'2017-03-22 08:42:56.157','POD8','POD8'), 
('00001','C33333333','Area2',3,333333333,'2017-03-22 08:22:59.157','POD8','POD8'), 
('00003','C33333333','Area3',1,333333333,'2017-03-23 06:41:12.753','','B46') 

GO 

這是我迄今爲止的查詢;這會給我上一行的價值和下一行的價值,但我不認爲這需要顧客考慮。

SELECT 
    T1.[User], T1.[CustomerID], 
    T1.[Area], T1.[Event], 
    T1.[VisitNumber], 
    T1.[CurrentRoom], T1.[NewRoom], 
    T1.[Time], 
    LAG(T1.TIME) OVER (ORDER BY T1.VisitNumber) PreviousTime, 
    LEAD(T1.TIME) OVER (ORDER BY T1.VisitNumber) NextTime 
FROM 
    #beds t1 
WHERE 
    T1.[Area] = 'Area2' 
    AND T1.[CurrentRoom] IS NOT NULL 
    AND T1.[NewRoom] IS NOT NULL 
    AND T1.[CustomerID] IS NOT NULL 
    AND T1.[CustomerID] <> ' ' 
    AND T1.Event IN (1,9) 
ORDER BY 
    VisitNumber DESC 

預期輸出:這是我期待的輸出。我只希望TimeInRoom(不包括從時間日期字段):

+------------+-------+-------------+-------------+---------+------------+ 
| CustomerID | Area | VisitNumber | CurrentRoom | NewRoom | TimeInRoom | 
+------------+-------+-------------+-------------+---------+------------+ 
|C33333333 |Area2 | 333333333 |    | BB4  | 00:10  | 
|C33333333 |Area2 | 333333333 |    | POD8 | 00:20  | 
|C33333333 |Area2 | 333333333 | POD8  |   | 00:30  | 
+------------+-------+-------------+-------------+---------+------------+ 
+2

這是怎麼問的好SQL問題一個很好的例子。 +1。 –

+1

除了列不匹配... – jarlh

+0

@iamrichhowell:你確定你的樣本數據與你的描述是一致的嗎? – etsa

回答

4

我希望這有助於:

;WITH cte_Result AS 
(
    SELECT 
     [CustomerID], 
     [Area], 
     [VisitNumber], 
     [CurrentRoom], 
     [NewRoom], 
     [Time], 
     LAG([TIME]) OVER (partition by [CustomerID],[VisitNumber] ORDER BY ID DESC) PreviousTime, 
     LEAD([TIME]) OVER (partition by [CustomerID],[VisitNumber] ORDER BY ID DESC) NextTime 
    FROM #beds 
    WHERE [Area] = 'Area2' 
     AND [CurrentRoom] IS NOT NULL 
     AND [NewRoom] IS NOT NULL 
     AND [CustomerID] IS NOT NULL 
     AND [CustomerID] <> ' ' 
     AND [Event] IN (1,9) 
     --AND [CustomerID] = 'C33333333' 
), 
cte_BuildStayPeriod 
AS (
    SELECT CustomerID, 
     Area, 
     VisitNumber, 
     CurrentRoom, 
     NewRoom, 
     DATEDIFF(SECOND, COALESCE([NextTime], PreviousTime), COALESCE(PreviousTime, [time])) AS StayDuration 
    FROM cte_Result 
) 
SELECT CustomerID, 
    Area, 
    VisitNumber, 
    CurrentRoom, 
    NewRoom, 
    StayDuration, 
    CAST(DATEADD(SECOND, StayDuration, '1900-01-01') AS TIME) AS StayDuration 
FROM cte_BuildStayPeriod 
+0

這工作完美,非常感謝你的幫助。 – sqlrich

4

可能是我不很明白你的問題,但要儘量使用條款PARTITION BY內的LAG/LEAD功能:

,LAG(T1.TIME) OVER (PARTITION BY CustomerID ORDER BY T1.VisitNumber) PreviousTime 
,LEAD(T1.TIME) OVER (PARTITION BY CustomerID ORDER BY T1.VisitNumber) NextTime 
0

在您的示例中,當客戶訪問一次時,您將遇到問題,並且使用滯後/潛在客戶會得到另一個客戶的訪問信息。

試試:

SELECT 
    T1.[User], T1.[CustomerID], 
    T1.[Area], T1.[Event], 
    T1.[VisitNumber], 
    T1.[CurrentRoom], T1.[NewRoom], 
    T1.[Time], 
    (select TOP (1) t.Time from #beds t where t.[CustomerID] = T1.[CustomerID] and t.Time<T1.Time order by t.Time desc) PreviousTime, 
    (select TOP (1) t.Time from #beds t where t.[CustomerID] = T1.[CustomerID] and t.Time>T1.Time order by t.Time) NextTime 
FROM 
    #beds t1 
WHERE 
    T1.[Area] = 'Area2' 
    AND T1.[CurrentRoom] IS NOT NULL 
    AND T1.[NewRoom] IS NOT NULL 
    AND T1.[CustomerID] IS NOT NULL 
    AND T1.[CustomerID] <> ' ' 
    AND T1.Event IN (1,9) 
ORDER BY 
    VisitNumber DESC 
相關問題