SQL返回两行之间的秒差

时间:2017-05-16 09:52:38

标签: sql-server

此问题与SQL Server有关。我有下表:

id    size   batch code   product code      additiontime
--------------------------------------------------------
1       91      55555       BigD Red        2017-05-15 13:00:00
2       91      55555       BigD Red        2017-05-15 13:00:05
3       94      55555       BigD Red        2017-05-15 13:00:15
4       91      44444       BigD Blue       2017-05-15 14:10:00
5       92      44444       BigD Blue       2017-05-15 14:15:00
6       93      44444       BigD Blue       2017-05-15 14:20:00
7       94      44444       BigD Blue       2017-05-15 14:30:00
8       91      33333       BigD Orange     2017-05-15 15:00:00
9       91      33333       BigD Orange     2017-05-15 15:00:10
10      94      33333       BigD Orange     2017-05-15 15:00:15

执行此SQL语句时:

select *
from mytable y1
where size = 91 
  and not exists (select 1
                  from mytable y2
                  where y1.productcode = y2.productcode and y2.size = 92)

我得到以下结果:

id    size   batch code   product code      additiontime
--------------------------------------------------------
1       91      55555       BigD Red        2017-05-15 13:00:00
2       91      55555       BigD Red        2017-05-15 13:00:05
8       91      33333       BigD Orange     2017-05-15 15:00:00
9       91      33333       BigD Orange     2017-05-15 15:00:10

我想修改上面的查询,以便每个批次代码显示一行,并添加一个额外的列以显示每个批次代码组的第一个和第二个记录之间的秒数差异,例如:

id    size   batch code   product code      additiontime            seconds difference
--------------------------------------------------------------------------------------
1       91      55555       BigD Red        2017-05-15 13:00:00     5
8       91      33333       BigD Orange     2017-05-15 15:00:00     10

我尝试过以下SQL,它几乎可以解决这个问题,但它会返回多行,而不是每批代码只返回一行:

WITH rows AS
(
    SELECT 
        *, 
        ROW_NUMBER() OVER (ORDER BY AdditionTime) AS rn 
    FROM 
        mytable y1
    WHERE
        size = 91 
        AND NOT EXISTS (SELECT *
                        FROM mytable y2
                        WHERE y1.productcode = y2.productcode AND y2.size = 92)
)
SELECT DATEDIFF(second, mc.AdditionTime, mp.AdditionTime)
FROM rows mc
JOIN rows mp ON mc.rn = mp.rn - 1

我的SQL知识不是很好。我确信它可以产生正确的结果,但我已经尝试了所有方法但没有成功。提前感谢任何指针。

4 个答案:

答案 0 :(得分:2)

这为您提供了所需的输出,并在cte的结果上进行了自联接。另外,我在PARTITION BY添加了ROW_NUMBER()

CREATE TABLE #mytable
    (
      id INT ,
      size INT ,
      batchCode INT ,
      productCode NVARCHAR(30) ,
      additiontime DATETIME
    );


INSERT  INTO #mytable
        ( id, size, batchCode, productCode, additiontime )
VALUES  ( 1, 91, 55555, 'BigD Red', '2017-05-15 13:00:00' ),
        ( 2, 91, 55555, 'BigD Red', '2017-05-15 13:00:05' ),
        ( 3, 94, 55555, 'BigD Red', '2017-05-15 13:00:15' ),
        ( 4, 91, 44444, 'BigD Blue', '2017-05-15 14:10:00' ),
        ( 5, 92, 44444, 'BigD Blue', '2017-05-15 14:15:00' ),
        ( 6, 93, 44444, 'BigD Blue', '2017-05-15 14:20:00' ),
        ( 7, 94, 44444, 'BigD Blue', '2017-05-15 14:30:00' ),
        ( 8, 91, 33333, 'BigD Orange', '2017-05-15 15:00:00' ),
        ( 9, 91, 33333, 'BigD Orange', '2017-05-15 15:00:10' ),
        ( 10, 94, 33333, 'BigD Orange', '2017-05-15 15:00:15' );
WITH    rows
          AS ( SELECT   * ,
                        ROW_NUMBER() OVER ( PARTITION BY y1.batchCode ORDER BY additiontime ) AS rn
               FROM     #mytable y1
               WHERE    size = 91
                        AND NOT EXISTS ( SELECT *
                                         FROM   #mytable y2
                                         WHERE  y1.productCode = y2.productCode
                                                AND y2.size = 92 )
             )
    SELECT  t1.id ,
            t1.size ,
            t1.batchCode ,
            t1.productCode ,
            DATEDIFF(SECOND, t1.additiontime, t2.additiontime) SecondsDiff
    FROM    rows t1
            INNER JOIN rows t2 ON t2.batchCode = t1.batchCode
                                  AND t1.id != t2.id
    WHERE   t1.rn = 1; 

DROP TABLE #mytable

<强>产地:

id  size    batchCode   productCode  SecondsDiff
8   91      33333       BigD Orange  10
1   91      55555       BigD Red     5

注意,您应该使用更大的数据集进行测试,以确保准确性并考虑其他任何情况。

答案 1 :(得分:1)

你其实非常接近! :) 唯一缺少的是在JOIN的{​​{1}}上添加另一个条件,以便您只比较具有相同CTE的行,如下所示:

product code

PS。假设您知道每个产品有两行。

答案 2 :(得分:1)

;With cte(id,size,batchcode,productcode,additiontime)
AS
(
SELECT 1 , 91, 55555,'BigD Red'   ,'2017-05-15 13:00:00' UNION ALL
SELECT 2 , 91, 55555,'BigD Red'   ,'2017-05-15 13:00:05' UNION ALL
SELECT 3 , 94, 55555,'BigD Red'   ,'2017-05-15 13:00:15' UNION ALL
SELECT 4 , 91, 44444,'BigD Blue'  ,'2017-05-15 14:10:00' UNION ALL
SELECT 5 , 92, 44444,'BigD Blue'  ,'2017-05-15 14:15:00' UNION ALL
SELECT 6 , 93, 44444,'BigD Blue'  ,'2017-05-15 14:20:00' UNION ALL
SELECT 7 , 94, 44444,'BigD Blue'  ,'2017-05-15 14:30:00' UNION ALL
SELECT 8 , 91, 33333,'BigD Orange','2017-05-15 15:00:00' UNION ALL
SELECT 9 , 91, 33333,'BigD Orange','2017-05-15 15:00:10' UNION ALL
SELECT 10, 94, 33333,'BigD Orange','2017-05-15 15:00:15' 
)
SELECT id
    ,size
    ,batchcode
    ,productcode
    ,additiontime
    ,(SecondDiff - LEADadditiontimeSec) AS secondsDifference
FROM (
    SELECT *
        ,DATEPART(SECOND, additiontime) LEADadditiontimeSec
        ,DATEPART(SECOND, LEADadditiontime) SecondDiff
    FROM (
        SELECT *
            ,LEAD(additiontime) OVER (
                PARTITION BY batchcode
                ,size ORDER BY batchcode
                ) LEADadditiontime
        FROM cte o
    WHERE size = 91
     AND NOT EXISTS ( SELECT * FROM   cte i
                        WHERE  o.productCode = i.productCode
                        AND i.size = 92 )
        ) Dt
    ) Final
WHERE Final.SecondDiff IS NOT NULL
ORDER BY 1

输出

id  size    batchcode   productcode  additiontime           secondsDifference
------------------------------------------------------------------------------
1   91      55555       BigD Red     2017-05-15 13:00:00        5
8   91      33333       BigD Orange  2017-05-15 15:00:00        10

答案 3 :(得分:0)

希望以下查询能为您完成这项工作 -

SELECT id, size, [batch code], [product code], additiontime, DATEDIFF(SECOND, additiontime, next_addition_time) AS [seconds difference]
FROM
(
    SELECT *
        , LEAD(additiontime) OVER (PARTITION BY [batch code] ORDER BY additiontime) AS next_addition_time
        , ROW_NUMBER() OVER (PARTITION BY [batch code] ORDER BY additiontime) AS row_num
    FROM mytable
) AS t
WHERE row_num = 1;

首先,子查询按每个批次的添加时间排序行号。它还存储下一个添加时间值。然后,外部查询只选择第一行以及当前和下一个添加时间之间的差异。

请注意,如果数据很大,您应该将子查询移动到临时表。您也可以执行 ORDER BY 并在where子句中提供过滤器。