2016-10-12 2 views
2

私は多少新しいSQLですので、何か助けが必要です。前もって感謝します!SQL - 指定された値の間に連続した列値を追加します

私は現在のスキャンと次間の時間(秒)を計算するために結合を使用することができた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 

MS SQL Serverで以下のようなテーブルを持っていますスキャン(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 

私は= 900 TimeDiff <を持っていると、そのグループの最初のDateScannedで結果を表示する連続した行のために一緒にTimeDiff値を追加する必要があります。この例では、次のように表示されます。

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 

ありがとうございました。

+1

あなたはここにあなたのクエリを貼り付けてもらえますか? – Terminus

+0

データを再作成する時間がありません。最初のクエリを実行しますか?最初のステップをペーストします –

+0

私はクエリを追加しました。ありがとう – ti034

答えて

1

ここで重要な点は、連続する行をグループに分類することです。

1 - 現在および次の行の日付の日付を取得し、値が< = 900であることを確認し、すべての行に1を割り当て、残りの値に0を割り当てます。

2 - 次に、row_number()関数を使用して行をグループに分類します。

3 - 計算されたdiff_columnが各グループごとに< = 900である行をcteから選択します。

4 - 最後に、そのようなグループの最初の日付とそのグループの最大実行合計(< = 900)を取得します。

with grps as (
    select *, 
    row_number() over(partition by acctid order by datescanned) 
    - row_number() over(partition by acctid,col order by datescanned) grp 
    from 
    (select *, 
    datediff(second,datescanned,lead(datescanned) over(partition by acctid order by datescanned)) as diff_column, 
    case when datediff(second,datescanned,lead(datescanned) over(partition by acctid order by datescanned)) <=900 then 1 else 0 end col 
    from tablename) t 
    ) 
select distinct acctid, 
min(datescanned) over(partition by acctid,grp) first_date, 
max(grp_tot) over(partition by acctid,grp) grp_total 
from (select * 
     ,sum(diff_column) over(partition by acctid,grp order by datescanned) grp_tot 
     from grps 
     where diff_column <= 900 
    ) x 
where grp_tot <=900 

Sample Demo

+0

ありがとうございます!これは素晴らしい。 – ti034

+0

FYI、grp_totのover節に "UNBOUNDED PRBEDING AND UNBOUNDED FOLLING"の引数を追加しました。それ以外の場合、grp_totの実行合計が得られます。SELECT DISTINCTは、min(datescanned)の代わりに各グループのすべてのdatescannedを取得します。 – ti034

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

@ ti034これは、vkpの回答を書き込む別の方法です。彼らはデモがあり、そのような雄弁な解決策であるので、私は彼らの答えを編集したくなかったが、受け入れられなかったので、あなたはロジックに従うのに苦労したかもしれないと思ったが、vkpの答えは容認された解決策でなければならない。 –

+0

私は今朝すぐにそれを見ていただけです。私は今日の午後に試してみよう。ありがとうエリック! – ti034

関連する問題