簡體   English   中英

使用mssql選擇記錄鏈

[英]select a chain of records using mssql

我有一個在TimeLines中有記錄的表,我需要獲取構成45分鍾鏈的行。

1|2016-01-01 00:00
2|2016-01-01 00:30
3|2016-01-01 00:45
4|2016-01-01 01:00

我如何根據時間找到第二行,導致第二行,第三行和第四行在45分鍾內無法解散15分鍾的時間鏈? 1st和2nd不好,導致時間軸之間的間隔為30分鍾。

第二,第三和第四行是一致的時間軸鏈。 第二排加15分鍾-好的。 到那時,原因是存在第三行。 第三排加15分鍾-好的。 到那個時候原因已經存在第四行。 結果,我有45分鍾一致的時間軸鏈。

1行加15分鍾-不好。 導致時間00:15的日期不存在。

嘗試這個

    DECLARE @Tbl TABLE (Id INT, StartDate DATETIME)
INSERT INTO @Tbl
VALUES 
(1,'2016-01-01 00:00'),
(2,'2016-01-01 00:30'),
(3,'2016-01-01 00:45'),
(4,'2016-01-01 01:00')


;WITH CTE
AS
(
    SELECT
        Id ,
        StartDate,
        ROW_NUMBER() OVER (ORDER BY Id) AS RowId
    FROM
    @Tbl
)


SELECT
    CurRow.*,   
    CASE 
        WHEN 
            DATEDIFF(MINUTE, CurRow.StartDate, NextRow.StartDate ) = 15  OR
            DATEDIFF(MINUTE, PrevRow.StartDate, CurRow.StartDate ) = 15  
            THEN '15 MIN'
        ELSE 'NO' END Flag
FROM
    CTE CurRow LEFT JOIN 
    (SELECT *, C.RowId - 1 AS TmpRowId  FROM CTE C) NextRow ON CurRow.RowId = NextRow.TmpRowId LEFT JOIN 
    (SELECT *, C.RowId + 1 AS TmpRowId  FROM CTE C) PrevRow ON CurRow.RowId = PrevRow.TmpRowId

輸出:

Id  StartDate                   RowId   Flag
1   2016-01-01 00:00:00.000     1       NO
2   2016-01-01 00:30:00.000     2       15 MIN
3   2016-01-01 00:45:00.000     3       15 MIN
4   2016-01-01 01:00:00.000     4       15 MIN

如果我對您的理解正確,則可以使用LEAD / LAG:

WITH Src AS
(
    SELECT * FROM (VALUES 
    (1,'2016-01-01 00:00'),
    (2,'2016-01-01 00:30'),
    (3,'2016-01-01 00:45'),
    (4,'2016-01-01 01:00')) T(ID, [Date])
)
SELECT *, CASE WHEN LEAD([Date]) OVER (ORDER BY ID)=DATEADD(MINUTE, 15, [Date])
                 OR LAG([Date]) OVER (ORDER BY ID)=DATEADD(MINUTE, -15, [Date])
              THEN 'Chained' END [Status]
FROM Src

它產生:

ID  Date                Status
--  ----                ------
1   2016-01-01 00:00    NULL
2   2016-01-01 00:30    Chained
3   2016-01-01 00:45    Chained
4   2016-01-01 01:00    Chained

您可以使用OUTER APPLY和棘手的ROW_NUMBER()來做到這一點:

;WITH TimeLines AS (  --This CTE is similar to your table
SELECT *
FROM (VALUES
(1, '2016-01-01 00:00'),(2, '2016-01-01 00:30'),
(3, '2016-01-01 00:45'),(4, '2016-01-01 01:00'),
(5, '2016-01-01 01:05'),(6, '2016-01-01 01:07'),
(7, '2016-01-01 01:15'),(8, '2016-01-01 01:30'),
(9, '2016-01-01 01:45'),(10, '2016-01-01 02:00')
) as t(id, datum)
)
, cte AS (
SELECT  t.id,
        t.datum,
        CASE WHEN ISNULL(DATEDIFF(MINUTE,t1.datum,t.datum),0) != 15 THEN DATEDIFF(MINUTE,t.datum,t2.datum) ELSE 15 END as i
FROM TimeLines t  --in this cte with the help of
OUTER APPLY (     --OUTER APPLY we are getting next and previous dates to compare them
    SELECT TOP 1 * 
    FROM TimeLines 
    WHERE t.datum > datum 
    ORDER BY datum desc) t1
OUTER APPLY (
    SELECT TOP 1 * 
    FROM TimeLines 
    WHERE t.datum < datum 
    ORDER BY datum asc) t2
)

SELECT  *,  --this is final select to get rows you need with chaines
        (ROW_NUMBER() OVER (ORDER BY (SELECT 1))+2)/3 as seq
FROM cte
WHERE i = 15

輸出:

id  datum               i   seq
2   2016-01-01 00:30    15  1
3   2016-01-01 00:45    15  1
4   2016-01-01 01:00    15  1
7   2016-01-01 01:15    15  2
8   2016-01-01 01:30    15  2
9   2016-01-01 01:45    15  2
10  2016-01-01 02:00    15  3

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM