2017-05-16 1 views
3

이 질문은 SQL Server와 관련이 있습니다.두 행 간의 초 차이를 반환하는 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) 

나는 다음과 같은 결과를 얻을 : :이 SQL 문을 실행할 때

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 

가 :

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에 대한 지식이 크지 않다. 올바른 결과를 낼 수는 있지만 모든 방법을 시도해 보았습니다. 성공하지 못했습니다. 모든 포인터에 미리 감사드립니다.

+0

당신은 항상 두 행 사이에 차이를 할 것으로 기대합니까? 아니면 더 많이 기대합니까? 그렇다면 어떻게 diff를 계산하고 싶습니까? – Tanner

+0

SQL Server 2012 이상을 사용하는 경우 [창 기능] (https://www.simple-talk.com/sql/learn-sql-server/window-functions-in-sql-server/)을 사용할 수 있습니다. . over 절을 사용하면 이전 행을 선택하고 적절한 DATEDIFF를 수행 할 수 있습니다. – PacoDePaco

+0

@Tanner - 항상 2 행을 기대합니다. –

답변

2

는 CTE의 결과에 가입 할 수 있습니다.

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 

주, 당신은 정확성을 보장하고 다른 시나리오를 고려하도록 설정보다 큰 데이터를 테스트해야합니다 또한, 나는 PARTITION BYROW_NUMBER()받는 덧붙였다.

+0

완벽한, 감사합니다! –

+0

@XavierAnimoto 문제 없음 – Tanner

1

당신은 실제로 아주 가까이에 있습니다!

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 mc.*, DATEDIFF(second, mc.AdditionTime, mp.AdditionTime) AS Diff 
FROM rows mc JOIN rows mp ON mc.rn = mp.rn - 1 AND mc.ProductCode = mp.ProductCode 

PS를 : 당신은 아래와 같은 product code 만 행을 비교할 수 있도록 :) 유일한없는 것은 CTEJOIN에 다른 조건을 추가하는 것입니다. 제품 당 두 개의 행이 있다는 것을 알고 있다고 가정합니다.

+1

감사합니다. 나는 Tanner의 대답을 사용했으나 당신도 그 일을했습니다. –

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 
+0

감사합니다. UNION에 대해서는 확신하지 못했지만 일하기를 기대합니다. 태너의 대답을 받아 들였습니다. –

+0

안녕하세요, 나는 UNION All을 사용하여 데이터를 가져 오는 데 cte를 사용하고 임시 결과 세트를 작동 시켰습니다. Union은 모두 원하는 출력에 사용되지 않습니다. –

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 절에 필터를 지정할 수 있습니다.

+0

사례에 내러티브를 추가해 주셔서 감사합니다. SQL을 사용해 보지 않았지만이를 명심하십시오. –

+0

하위 쿼리/임시 테이블을 사용하지 않고 단일 쿼리 솔루션보다 ID 및 크기가 항상 일괄 처리 (추가 시간)에 대해 증분 순서 인 경우. 어떻게 진행되는지 알려주세요. – Shiblu

관련 문제