2

数百万行のデータベースからデータを取得するスクリプトに取り組んでおり、期間のギャップに問題があります。10 日未満のギャップはまったくギャップと見なすべきではないと判断しました。したがって、これらのギャップは削除する必要があります (以下の例を参照してください。太字の日付は、「実際の」関心期間を形成します)。

  • ID InDate OutDate
  • 1 2008-10-10 2009-02-05
  • 1 2009-02-08 2009-05-13
  • 1 2011-01-01 2011-05-20
  • 2 2007-03-17 2008-10-19
  • 2 2009-05-30 2010-10-12
  • 2 2010 年 10 月 14 日 2010 年 12 月 31

したがって、いくつかの問題が発生します。最初の問題は、単一の期間に変換される期間について、どの Outdate と Indate が互いに近いかを特定することです。次の問題は、Outdate を上位の行番号から下位の行番号 (つまり、テーブルの上) に移動することです。最後の問題は、現在重複している行を特定して取り除くことです。

以下の質問を解決しようとしました。最初の 2 つの問題は、表 #t4a で解決されています。テーブル #t4aa の戦略は、問題の重複行を新しい (ダミー) 変数でマークすることによって重複を取り除き、後の段階でそのような値 (1:s) をすべて取り除くことです。しかし、うまくいきません!すべての行は、1 でマークされるべきものであっても、0 でマークされます。何か提案はありますか?

-- この一時テーブルはギャップを測定し、新しい変数 OutDate2 を作成します。この変数は、小さなギャップ (11 日未満) の場合、元の値の代わりに次の Outdate を行に書き込みます。

WITH C AS (SELECT Id, InDate, OutDate, ROW_NUMBER() OVER (PARTITION BY Id ORDER BY InDate) Rownum FROM #t4 t4)  
SELECT cur.Rownum, cur.Id, cur.InDate CurInDate, cur.OutDate, nxt.InDate NxtInDate, DATEDIFF(day, cur.OutDate, nxt.InDate) Number_of_days,   
  CASE WHEN DATEDIFF(day, cur.OutDate, nxt.InDate)<11 AND DATEDIFF(day, cur.OutDate, nxt.InDate)>0 THEN nxt.OutDate ELSE cur.OutDate END AS OutDate2  
INTO #t4a  
FROM C cur  
LEFT OUTER JOIN C nxt ON (nxt.rownum=cur.rownum+1 AND nxt.Id=cur.Id)

-- この一時テーブルは、行の OVERLAP を識別するダミーを作成し、後の一時テーブルでこれらを削除できるようにします。動かないのはこのテーブルです。

WITH C AS (SELECT Id, InDate, OutDate, ROW_NUMBER() OVER (PARTITION BY Id ORDER BY InDate) rownum FROM #t4a)  
SELECT cur.Id, cur.InDate, nxt.OutDate2,   
  CASE WHEN cur.OutDate2 < nxt.InDate THEN 1.0 ELSE 0.0
  END AS Overlap  
INTO #t4aa  
FROM C cur  
LEFT OUTER JOIN C nxt on (cur.rownum=nxt.rownum+1 AND cur.Id=nxt.Id)
4

2 に答える 2

1

これは一種の概念的なものですが、いくつかのアイデアが得られるかもしれません

WITH C AS 
(SELECT Id, InDate, OutDate, ROW_NUMBER() OVER (PARTITION BY Id ORDER BY InDate) Rownum FROM #t4 t4) 

    select Cgood.* 
    from c 
    join C as Cgood 
      on Cgood.ID = C1.ID 
     and Cgood.Rownum = C.Rownum + 1
     and DATEDIFF(day, C.OutDate, nxt.InDate)>=11
    group by Cgood.* 
    union 
    select Cgood.*
    from c  
    join C as Cgood 
      on Cgood.ID = C1.ID 
     and Cgood.Rownum = 1 
     and C.Rownum = 2 
     and DATEDIFF(day, C.OutDate, nxt.InDate)>=11
    group by Cgood.* 
    union
    select cMerge.ID, c.Indate, cMerge.OutDate
    from c
    join C as cMerge 
      on cMerge.ID = C1.ID 
     and cMerge.Rownum = C.Rownum + 1
     and DATEDIFF(day, C.OutDate, cMerge.InDate) < 11
    group by cMerge.ID, c.Indate, cMerge.OutDate
    union
    select cMerge.ID, c.Indate, cMerge.OutDate
    from c
    join C as cMerge 
      on cMerge.ID = C1.ID 
     and cMerge.Rownum = 1 
     and C.Rownum = 2
     and DATEDIFF(day, C.OutDate, cMerge.InDate) < 11
    group b
于 2012-10-26T21:12:49.977 に答える
1

昨日、自分の質問を解決しました。最後の一時テーブルを取り除き、最初の一時テーブルにダミー変数の作成を組み込みました。ソリューションの核心は、後方と前方に結合することでした。

WITH C AS (SELECT Id, InDate, OutDate, ROW_NUMBER() OVER (PARTITION BY Id ORDER BY InDate) Rownum FROM #t4 t4)  
SELECT cur.Rownum, cur.Id, cur.InDate CurInDate, cur.OutDate, nxt.InDate NxtInDate, DATEDIFF(day, cur.OutDate, nxt.InDate) Number_of_days,  
CASE  
WHEN DATEDIFF(day, prv.OutDate, cur.InDate)<11  
AND DATEDIFF(day, prv.OutDate, cur.InDate)>0  
THEN 1.0  
ELSE 0.0  
END AS Overlap,      
CASE  
WHEN DATEDIFF(day, cur.OutDate, nxt.InDate)<11  
AND DATEDIFF(day, cur.OutDate, nxt.InDate)>0  
THEN nxt.OutDate  
ELSE cur.OutDate  
END AS OutDate2  
INTO #t4a  
FROM C cur  
LEFT OUTER JOIN C prv ON (prv.rownum=cur.rownum-1 AND prv.Id=cur.Id)  
LEFT OUTER JOIN C nxt ON (nxt.rownum=cur.rownum+1 AND nxt.Id=cur.Id)
于 2012-10-28T07:04:55.640 に答える