2016-07-09 11 views
0

私はテーブル(レコード)を持つレコードを持つときから項目が親項目にリンクされたときに:私は4つの主要なケースの上に表示さSQL Serverの - マージ/グループ化の連続タイムスタンプ

CHILD STARTDATE     ENDDATE      PARENT 
207  2013-12-18 12:45:59.017 2014-01-09 18:16:01.227  NULL 
207  2014-01-09 18:16:01.227 2016-03-03 09:54:28.757  NULL 
207  2016-03-03 09:54:28.757 2100-01-01 00:00:00.000  NULL 
10558 2016-03-03 18:10:34.877 2016-04-05 10:25:22.860  10557 
10558 2016-04-05 10:25:22.860 2016-04-05 11:33:10.493  10557 
10558 2016-04-05 11:33:10.493 2100-01-01 00:00:00.000  10557 
10596 2016-05-15 16:55:15.970 2016-05-16 10:00:00.000  10592 
10596 2016-05-16 10:00:00.000 2016-05-17 10:00:00.000  10593 
10596 2016-05-17 10:00:00.000 2100-01-01 00:00:00.000  10592 
10600 2012-12-18 12:45:59.017 2100-01-01 00:00:00.000  10599 


のために同じ子の場合、同じ子の場合、同じ親の値を持つ新しいレコード(10558)
同じ子の場合、親の変更を伴う新しいレコード(10596)
同じ子、1レコードのみ(10600)。だろう

207  2013-12-18 12:45:59.017  2100-01-01 00:00:00.000  NULL 
10558 2016-03-03 18:10:34.877  2100-01-01 00:00:00.000  10557 
10596 2016-05-15 16:55:15.970  2100-01-01 00:00:00.000  10592 
10596 2016-05-16 10:00:00.000  2016-05-17 10:00:00.000  10593 
10600 2012-12-18 12:45:59.017  2100-01-01 00:00:00.000  10599 

望ましい結果:

SELECT 
    CHILD 
, MIN(STARTDATE) as STARTDATE 
, MAX(ENDDATE) as ENDDATE 
, PARENT 
FROM RECORDS 
GROUP BY CHILD, PARENT 

は、アイテム10596のために、次の望まない結果につながる:子項目が使用して、古い親に戻って変更することができたよう

207  2013-12-18 12:45:59.017  2100-01-01 00:00:00.000  NULL 
10558 2016-03-03 18:10:34.877  2100-01-01 00:00:00.000  10557 
10596 2016-05-15 16:55:15.970  2016-05-16 10:00:00.000  10592 
10596 2016-05-16 10:00:00.000  2016-05-17 10:00:00.000  10593 
10596 2016-05-17 10:00:00.000  2100-01-01 00:00:00.000  10592 
10600 2012-12-18 12:45:59.017  2100-01-01 00:00:00.000  10599 

どのようにこれを達成するためのアイデアですか?

答えて

0

以下は、あなたの記録の連続(無重複)があることを前提としています

WITH cte 
AS 
(
    SELECT 
     * 
     , ROW_NUMBER() OVER (PARTITION BY CHILD ORDER BY STARTDATE) r 
    FROM RECORDS 
) 

, 
cte2 
AS 
(
    SELECT 
     t1.CHILD CHILD1 
     , t1.STARTDATE STARTDATE1 
     , t1.ENDDATE ENDDATE1 
     , t1.PARENT PARENT1 
     , t1.r r1 
     , t2.CHILD CHILD2 
     , t2.STARTDATE STARTDATE2 
     , t2.ENDDATE ENDDATE2 
     , t2.PARENT PARENT2 
     , t2.r r2 
    FROM 
     cte t1 
     LEFT JOIN cte t2 ON 
      t1.CHILD = t2.CHILD 
      AND t1.r = t2.r - 1 
    WHERE 
     t1.PARENT != t2.PARENT 
     OR (t1.PARENT IS NULL AND t2.PARENT IS NOT NULL) 
     OR (t2.PARENT IS NULL AND t1.PARENT IS NOT NULL) 
     OR t2.r IS NULL 
) 

SELECT 
    CHILD1 CHILD 
    , 
     ISNULL 
      (
       (
        SELECT MIN(STARTDATE) 
        FROM RECORDS 
        WHERE 
         CHILD = CHILD1 
         AND (PARENT = PARENT1 OR (PARENT IS NULL AND PARENT1 IS NULL)) 
         AND STARTDATE >= 
          (
           SELECT ENDDATE1 
           FROM cte2 cte2INNER 
           WHERE 
            cte2INNER.CHILD1 = cte2OUTER.CHILD1 
            AND cte2INNER.r2 = 
             (
              SELECT MAX(cteINNER2.r2) 
              FROM cte2 cteINNER2 
              WHERE 
               cteINNER2.CHILD1 = cte2OUTER.CHILD1 
               AND cteINNER2.r2 <= cte2OUTER.r1 
             ) 
          ) 
       ) 
       , 
        (
         SELECT MIN(STARTDATE) 
         FROM RECORDS 
         WHERE CHILD = CHILD1 
        ) 
      ) 
      STARTDATE 
    , ENDDATE1 ENDDATE 
    , PARENT1 PARENT 
FROM cte2 cte2OUTER 

それは一時テーブルで迅速に実行されます。

WITH cte 
AS 
(
    SELECT 
     * 
     , ROW_NUMBER() OVER (PARTITION BY CHILD ORDER BY STARTDATE) r 
    FROM RECORDS 
) 


SELECT 
    t1.CHILD CHILD1 
    , t1.STARTDATE STARTDATE1 
    , t1.ENDDATE ENDDATE1 
    , t1.PARENT PARENT1 
    , t1.r r1 
    , t2.CHILD CHILD2 
    , t2.STARTDATE STARTDATE2 
    , t2.ENDDATE ENDDATE2 
    , t2.PARENT PARENT2 
    , t2.r r2 
INTO #RECORDSTEMP 
FROM 
    cte t1 
    LEFT JOIN cte t2 ON 
     t1.CHILD = t2.CHILD 
     AND t1.r = t2.r - 1 
WHERE 
    t1.PARENT != t2.PARENT 
    OR (t1.PARENT IS NULL AND t2.PARENT IS NOT NULL) 
    OR (t2.PARENT IS NULL AND t1.PARENT IS NOT NULL) 
    OR t2.r IS NULL 

SELECT 
    CHILD1 CHILD 
    , 
     ISNULL 
      (
       (
        SELECT MIN(STARTDATE) 
        FROM RECORDS 
        WHERE 
         CHILD = CHILD1 
         AND (PARENT = PARENT1 OR (PARENT IS NULL AND PARENT1 IS NULL)) 
         AND STARTDATE >= 
          (
           SELECT ENDDATE1 
           FROM #RECORDSTEMP rtmpINNER 
           WHERE 
            rtmpINNER.CHILD1 = rtmpOUTER.CHILD1 
            AND rtmpINNER.r2 = 
             (
              SELECT MAX(rtmpINNER2.r2) 
              FROM #RECORDSTEMP rtmpINNER2 
              WHERE 
               rtmpINNER2.CHILD1 = rtmpOUTER.CHILD1 
               AND rtmpINNER2.r2 <= rtmpOUTER.r1 
             ) 
          ) 
       ) 
       , 
        (
         SELECT MIN(STARTDATE) 
         FROM RECORDS 
         WHERE CHILD = CHILD1 
        ) 
      ) 
      STARTDATE 
    , ENDDATE1 ENDDATE 
    , PARENT1 PARENT 
FROM #RECORDSTEMP rtmpOUTER 

DROP TABLE #RECORDSTEMP 
0

は、それが動作しますが、あなたの答えをいただき、ありがとうございます。

私もこのソリューション受け

WITH DISTINCTRECORDS as (
       SELECT 
       CHILD 
       , 
       CASE 
       WHEN 
       (
        CHILD = lag(CHILD) over(order by CHILD,STARTDATE, ENDDATE, PARENT) 
        AND 
        STARTDATE = lag(ENDDATE) over(order by CHILD,STARTDATE, ENDDATE, PARENT) 
        AND 
        (PARENT = lag(PARENT) over(order by CHILD,STARTDATE, ENDDATE, PARENT) OR (PARENT is null AND lag(PARENT) over(order by CHILD,STARTDATE, ENDDATE, PARENT) is null )) 
       ) 
        OR 
       (
        CHILD = lead(CHILD) over(order by CHILD,STARTDATE, ENDDATE, PARENT) 
        AND 
        ENDDATE = lead(STARTDATE) over(order by CHILD,STARTDATE, ENDDATE, PARENT) 
        AND 
        (PARENT = lead(PARENT) over(order by CHILD,STARTDATE, ENDDATE, PARENT) OR (PARENT is null AND lead(PARENT) over(order by CHILD,STARTDATE, ENDDATE, PARENT) is null )) 
       ) 
       THEN 1 
       ELSE 0 
       END ToBeMerged 
       , STARTDATE 
       , ENDDATE 
       , PARENT 

       FROM RECORDS 
) 

SELECT CHILD, min(STARTDATE) STARTDATE, max(ENDDATE) ENDDATE, PARENT FROM DISTINCTRECORDS WHERE ToBeMerged = 1 GROUP BY CHILD, PARENT 
UNION ALL 
SELECT CHILD, STARTDATE, ENDDATE, PARENT FROM DISTINCTRECORDS WHERE ToBeMerged = 0 

1が最高のパフォーマンスを持っているでしょうか?

+0

ここに投稿したクエリは、はるかに速く実行されます(これらのLAG関数とLEAD関数について聞いたことはありません)。私はまた、データがすでにCHILDとPARENTのチェックで注文されているので、STARTDATE節とENDDATE節を削除できると思います。(終わりの(前のレコード)とstart(現在のレコード) –

+0

実際には、同じ親レコードと複数のレコードを持つ2つのグループが存在する場合、このクエリは機能しません - それらはすべて一緒にグループ化されます –

+0

具体的にすることはできますか? –

関連する問題