2017-05-16 8 views
3

この質問はSQL Serverに関連しています。私は、このSQL文を実行すると2行の秒の差を返す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 

私は上記のクエリを変更したいと思います:

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

を私は次のような結果を得る私は、次の表を持っていますバッチコードごとに1行が表示され、各バッチコードグループの1番目と2番目のレコードの間の秒数を示す追加の列が追加されます。

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を、試してみましたが、それは代わりにバッチコードごとに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 DATEDIFF(second, mc.AdditionTime, mp.AdditionTime) 
FROM rows mc 
JOIN rows mp ON mc.rn = mp.rn - 1 

マイSQLの知識は素晴らしいではありません。正しい結果を生み出すことは可能だと確信していますが、私は成功していないすべての方法を試しました。どのポインタについても事前に感謝します。

+0

あなたはいつも2つの行を持っていると思いますか?もしそうなら、どのように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の結果に自己結合を有する所望の出力を提供します。また、私はROW_NUMBER()PARTITION BYを追加しました:

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 

注意を、あなたは正確性を確保し、他のシナリオのアカウントを取るために、より大きなデータセットでテストする必要があります。

+0

完璧、ありがとう! –

+0

@XavierAnimoto問題なし – Tanner

1

あなたは実際にはかなり近いです! :) 唯一欠けているものは、あなたが以下のように同じproduct codeで行のみを比較するように、CTEJOINに別の条件を追加することです:

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。製品ごとに2つの行があることがわかっていると仮定します。

+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を使用してデータを取得し、一時的な結果セットを処理します.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

関連する問題