SQL - 在给定值之间添加连续列值

时间:2016-10-12 16:48:10

标签: sql sql-server

我对SQL有点新,需要一些帮助。提前谢谢!

我在MS SQL Server 2014中有一个类似于下面的表。

AcctID  DateScanned
16      2015-12-09 13:24:19.000
16      2015-12-09 13:24:43.000
16      2015-12-09 13:25:49.000
16      2016-02-10 11:19:58.000
16      2016-02-10 11:20:26.000
16      2016-02-20 10:18:54.000
16      2016-02-20 10:18:56.000
16      2016-02-20 10:18:58.000
16      2016-05-23 11:39:47.000
16      2016-06-08 13:02:11.000
16      2016-08-31 20:02:10.000
16      2016-09-14 15:30:40.000
16      2016-09-14 15:31:31.000

我已经能够使用连接来计算当前扫描和下一次扫描(TimeDiff)之间的时间(以秒为单位)。

SELECT a.AcctID, a.DateScanned, MIN(b.DateScanned) AS NextScan
        , DATEDIFF(SECOND,a.DateScanned, MIN(b.DateScanned)) AS TimeDiff, 
FROM myTable a
    LEFT JOIN myTable b
        ON a.AcctID = b.AcctID AND a.DateScanned < b.DateScanned
GROUP BY a.AcctID, a.DateScanned



AcctID  DateScanned                NextScan                  TimeDiff
16      2015-12-09 13:24:19.000    2015-12-09 13:24:43.000   24
16      2015-12-09 13:24:43.000    2015-12-09 13:25:49.000   66
16      2015-12-09 13:25:49.000    2016-02-10 11:19:58.000   5435649
16      2016-02-10 11:19:58.000    2016-02-10 11:20:26.000   28
16      2016-02-10 11:20:26.000    2016-02-20 10:18:54.000   860308
16      2016-02-20 10:18:54.000    2016-02-20 10:18:56.000   2
16      2016-02-20 10:18:56.000    2016-02-20 10:18:58.000   2
16      2016-02-20 10:18:58.000    2016-05-23 11:39:47.000   8040049
16      2016-05-23 11:39:47.000    2016-06-08 13:02:11.000   1387344
16      2016-06-08 13:02:11.000    2016-08-31 20:02:10.000   7282799
16      2016-08-31 20:02:10.000    2016-09-14 15:30:40.000   1193310
16      2016-09-14 15:30:40.000    2016-09-14 15:31:31.000   51
16      2016-09-14 15:31:31.000    NULL                      NULL

我需要将TimeDiff值一起添加到具有TimeDiff&lt; = 900的连续行中,并使用该组的第一个DateScanned显示结果。对于这个例子,我会看到:

AcctID  DateScanned                Result
16      2015-12-09 13:24:19.000    90
16      2016-02-10 11:19:58.000    28
16      2016-02-20 10:18:54.000    4
16      2016-09-14 15:30:40.000    51

再次感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

这里的关键是将连续的行分组。

1 - 获取当前行和下一行日期的日期,并检查该值是否为&lt; = 900,并为所有这些行分配1,为剩余的行分配0。

2 - 然后使用row_number()函数将行分类为组。

3 - 从每个组的计算diff_column&lt; = 900的cte中选择行。

4 - 最后得到这些组的第一个日期和这些组的最大运行总数(&lt; = 900)。

dense_rank()

Sample Demo

答案 1 :(得分:0)

IF OBJECT_ID('tempdb..#Scans') IS NOT NULL DROP TABLE #Scans;
CREATE TABLE #Scans (AcctID INT, DateScanned DATETIME);

INSERT #Scans VALUES
(16,'2015-12-09 13:24:19.000'),
(16,'2015-12-09 13:24:43.000'),
(16,'2015-12-09 13:25:49.000'),
(16,'2016-02-10 11:19:58.000'),
(16,'2016-02-10 11:20:26.000'),
(16,'2016-02-20 10:18:54.000'),
(16,'2016-02-20 10:18:56.000'),
(16,'2016-02-20 10:18:58.000'),
(16,'2016-05-23 11:39:47.000'),
(16,'2016-06-08 13:02:11.000'),
(16,'2016-08-31 20:02:10.000'),
(16,'2016-09-14 15:30:40.000'),
(16,'2016-09-14 15:31:31.000');

WITH Baseline AS
(
    SELECT AcctID,
        DateScanned,
        LEAD(DateScanned) OVER (PARTITION BY AcctID ORDER BY DateScanned) AS NextScan,
        CASE 
            WHEN DATEDIFF(SECOND, DateScanned, LEAD(DateScanned) OVER (PARTITION BY AcctID ORDER BY DateScanned)) <= 900 
                THEN 1 
            ELSE 
                0 
        END AS ValidRecord
    FROM #Scans s
), CreateGroups AS
(
    SELECT *,
        ROW_NUMBER() OVER(PARTITION BY AcctID ORDER BY DateScanned) - 
            ROW_NUMBER() OVER(PARTITION BY AcctID, ValidRecord ORDER BY DateScanned) AS GroupID
    FROM Baseline
)
SELECT AcctID,
    MIN(DateScanned) AS DateScanned,
    DATEDIFF(SECOND,MIN(DateScanned),MAX(NextScan)) AS [Result]
FROM CreateGroups
WHERE ValidRecord = 1
GROUP BY AcctID, GroupID