2017-03-29 8 views
0

私はこの問題でしばらくの間苦労しており、何か助けが必要です。 私は次のクエリを持っています。しかし、私が持っているときに、クエリ結果に見ることができるようSQL Server 2012以降:期間別に要素をマージする

enter image description here

CREATE TABLE Example(
Start NVARCHAR(8), 
Endd NVARCHAR(8), 
Col1 NVARCHAR(2), 
Col2 NVARCHAR(2)); 

INSERT into Example (Start,Endd,Col1,Col2) 
VALUES ('20130801','20140316','02','01'), 
('20140317','20140319','04','02'), 
('20140320','20140320','04','02'), 
('20140321','20140421','02','Z8'), 
('20140422','20140429','02','Z9'), 
('20140430','20140902','04','02'), 
('20140903','20150201','04','02'), 
('20150202','20150223','04','02'), 
('20150224','20150527','04','02'), 
('20150528','99991231','04','02') 
; 

select MIN(Start)AS Start,MAX(Endd) AS Endd,Col1,Col2 from 
(
    SELECT top (100000000) Start, Endd,Col1, Col2,dense_rank() over(partition by Col1, Col2 order by Start,Endd) as rank 
    ,LEAD (Col1) OVER (order by Start,Endd DESC) as l1 
    ,LEAD (Col2) OVER (order by Start,Endd DESC) as l2 
    ,LAG (Col1) OVER (order by Start,Endd DESC) as l11 
    ,LAG (Col2) OVER (order by Start,Endd DESC) as l22 
    FROM Example sp 
    order by Start,Endd 
)rq 
GROUP BY Col1,Col2,case when (rq.l1=Col1 and rq.l2=Col2) or (rq.l11=Col1 and rq.l22=Col2) then 0 else rank end 
order by Start,Endd; 

は、私の目標は、次の結果を持って、それらのデータをマージすることです異なる期間のCol1とCol2の値が同じ場合、マージは正しく行われません。基本的には、それらをすべて1つにマージして、新しい期間の値に問題を作り出します。

誰かが私を助けることができるでしょうか?

+1

を使用してこれを改善する必要があります。クエリを投稿する必要があります。 –

+1

[ask]を読んで質問を編集して、サンプルデータとクエリの関連テーブルDDL + DMLをテキストとして入力してください。 –

+0

ご迷惑をおかけして申し訳ありません、初めて投稿しました:)私は、クエリ自体へのリンクをいくつか変更しました。うまくいけば、それはあなたのために簡単になります! – BlitzX

答えて

0

あなたはあなたの質問に近づいていました。あなたは今までに解決策を見つけたかもしれません。これは古典的な島と隙間の問題です。私はLEADLAGを使用しない長いバージョンを提供しています。おそらく密度の高いランクでこれらのウィンドウ関数を使用して、おそらく以下のコードの45%を置き換えることができます。

DECLARE @Example TABLE(
Start NVARCHAR(8), 
Endd NVARCHAR(8), 
Col1 NVARCHAR(2), 
Col2 NVARCHAR(2)); 

INSERT into @Example (Start,Endd,Col1,Col2) 
VALUES ('20130801','20140316','02','01'), 
('20140317','20140319','04','02'), 
('20140320','20140320','04','02'), 
('20140321','20140421','02','Z8'), 
('20140422','20140429','02','Z9'), 
('20140430','20140902','04','02'), 
('20140903','20150201','04','02'), 
('20150202','20150223','04','02'), 
('20150224','20150527','04','02'), 
('20150528','99991231','04','02') 

SELECT 
    TableID=MAX(TableID),Col1=MAX(Col1),Col2=MAX(Col2),Start=MIN(Start),Endd=MAX(Endd) 
FROM 
(
    SELECT 
     TableID,Col1,Col2,Start,Endd,ChangeID=MAX(ChangeOnlyTableID) 
    FROM 
    (
     SELECT 
      AllRecords.TableID,AllRecords.Col1,AllRecords.Col2,AllRecords.Start,AllRecords.Endd,ChangeOnlyTableID=ChangesOnly.TableID 
     FROM 
     (
      SELECT * FROM 
      (
       SELECT 
        This.Start,This.Endd,This.TableID,This.Col1,This.Col2, 
        Changed=CASE WHEN (Next.Col1=This.Col1 AND Next.Col2=This.Col2) THEN 0 ELSE 1 END 
       FROM 
       ( 
        SELECT TableID=ROW_NUMBER() OVER(ORDER BY Start,Endd,Col1,Col2),Start,Endd,Col1,Col2 FROM @Example 
       )AS This 
       LEFT OUTER JOIN 
       (
        SELECT TableID=ROW_NUMBER() OVER(ORDER BY Start,Endd,Col1,Col2),Start,Endd,Col1,Col2 FROM @Example 
       ) 
       AS Next ON This.TableID=Next.TableID+1 
      ) 
      AS ChangeMarkers 
      WHERE Changed=1 
     ) 
     AS AllRecords 
     INNER JOIN 
     (
      SELECT * FROM 
      (
       SELECT 
        This.Start,This.Endd,This.TableID,This.Col1,This.Col2, 
        Changed=CASE WHEN (Next.Col1=This.Col1 AND Next.Col2=This.Col2) THEN 0 ELSE 1 END 
       FROM 
        (
         SELECT TableID=ROW_NUMBER() OVER(ORDER BY Start,Endd,Col1,Col2),Start,Endd,Col1,Col2 FROM @Example 
        ) AS This 
        LEFT OUTER JOIN 
        (
         SELECT TableID=ROW_NUMBER() OVER(ORDER BY Start,Endd,Col1,Col2),Start,Endd,Col1,Col2 FROM @Example 
        ) AS Next ON This.TableID=Next.TableID+1 
      ) 
      AS ChangeMarkers 
       WHERE Changed=1 
     ) 
     AS ChangesOnly ON ChangesOnly.Col1=AllRecords.Col1 AND ChangesOnly.Col2=AllRecords.Col2 AND ChangesOnly.TableID<=AllRecords.TableID 
    )AS JoinedResults 
    GROUP BY 
     TableID,Col1,Col2,Start,Endd 
) 
AS Final 
GROUP BY 
    Col1,Col2,ChangeID 
ORDER BY 
    MAX(TableID) 

のようなクエリを生成するために、いくつかのCTEのと、ややこれを短縮することもできます。しかし、私が行った更なる仮想キーを使用して適用することができるいくつかの巧妙なハックでもあります

;WITH TableWithIDs AS 
( 
    SELECT TableID=ROW_NUMBER() OVER(ORDER BY Start,Endd,Col1,Col2),Start,Endd,Col1,Col2 FROM @Example 
) 
,ChangeMarkers AS 
(
    SELECT 
     This.Start,This.Endd,This.TableID,This.Col1,This.Col2, 
     Changed=CASE WHEN (Next.Col1=This.Col1 AND Next.Col2=This.Col2) THEN 0 ELSE 1 END 
    FROM 
     TableWithIDs AS This 
     LEFT OUTER JOIN TableWithIDs AS Next ON This.TableID=Next.TableID+1 
) 
,ChangesOnly AS 
(
    SELECT * FROM ChangeMarkers WHERE Changed=1 
) 
, 
JoinedResults AS 
(
    SELECT 
     AllRecords.TableID,AllRecords.Col1,AllRecords.Col2,AllRecords.Start,AllRecords.Endd,ChangeOnlyTableID=ChangesOnly.TableID 
    FROM 
     ChangeMarkers AllRecords 
     INNER JOIN ChangesOnly ON ChangesOnly.Col1=AllRecords.Col1 AND ChangesOnly.Col2=AllRecords.Col2 AND ChangesOnly.TableID<=AllRecords.TableID 
) 

SELECT 
    TableID=MAX(TableID),Col1=MAX(Col1),Col2=MAX(Col2),Start=MIN(Start),Endd=MAX(Endd) 
FROM 
(
    SELECT 
     TableID,Col1,Col2,Start,Endd,ChangeID=MAX(ChangeOnlyTableID) 
    FROM 
     JoinedResults 
    GROUP BY 
     TableID,Col1,Col2,Start,Endd 
) 
AS Final 
GROUP BY 
    Col1,Col2,ChangeID 
ORDER BY 
    MAX(TableID) 

最も直接的だがもっと冗長なルート。 DENSE_RANK()LEAD()またはLAG()

+0

これをありがとう:)私はこれを試して戻ってくるでしょう。私はまだあなたのコードをそれらのリードと遅れ関数で置き換えるほど熟練していませんが、私は一見しようとします。多分それを行う場所のいくつかのキー? – BlitzX