2016-08-23 7 views
3

私は親子関係にあるトランザクションを持つSQLテーブルを持っています。しかし、この関係は、行と型の列によってのみ決定されます。他の参照はありません。私はこの参照を構築する必要があります。親子行をグループ化する方法(TSQL)

DECLARE @tmp TABLE (line INT, type CHAR(1), product VARCHAR(30)) 
INSERT @tmp VALUES 
       (1,' ','22411') 
      ,(2,' ','22413') 
      ,(3,'P','27050') 
      ,(4,'C','22492') 
      ,(5,'C','22493') 
      ,(6,'C','22490') 
      ,(7,' ','22410') 
      ,(8,' ','22511') 
      ,(9,'P','27051') 
      ,(10,'C','22470') 
      ,(11,'C','22471') 
      ,(12,'C','22473') 
      ,(13,'C','22474') 
      ,(14,' ','22015') 
      ,(15,' ','22167') 
      ,(16,' ','12411') 
      ,(17,' ','22500') 

ライン3は親製品です。 4行目から6行目は子行です。 9行目はもう1つの親製品です。 10行目から13行目は子行です。カーソルなしでこれを達成するためにどのように

line|type|product|group 
1 | |22411 |1 
2 | |22413 |2 
3 |P |27050 |3 
4 |C |22492 |3 
5 |C |22493 |3 
6 |C |22490 |3 
7 | |22410 |7 
8 | |22511 |8 
9 |P |27051 |9 
10 |C |22470 |9 
11 |C |22471 |9 
12 |C |22473 |9 
13 |C |22474 |9 
14 | |22015 |14 
15 | |22167 |15 
16 | |12411 |16 
17 | |22500 |17 

所望の出力は、親子ラインがグループ化され、このようなもの、ありますか?

+0

'order'カラムとは何ですか?それは 'line'列ですか? –

+0

@RaduGheorghiuはい。ヒントのためのThx。私はテキストで修正しました。 –

答えて

1

これは、使用しているバージョンを指定していないため、ほぼすべてのバージョンのSQL Serverで機能します。

しかし、少なくともSQL Server 2012を使用している場合は、@ qxgのソリューションを使用することができます。それは、単一のクエリではないとはいえここで

は、あなたが必要なコードですが、それはあなたが望む結果を得られます。「あなたは、おそらくそれは、単一のクエリであることをリファクタリングできますが、私はドン

CREATE TABLE #tmp (line INT, type CHAR(1), product VARCHAR(30)) 
INSERT #tmp VALUES (1,' ','22411') 
      ,(2,' ','22413') 
      ,(3,'P','27050') 
      ,(4,'C','22492') 
      ,(5,'C','22493') 
      ,(6,'C','22490') 
      ,(7,' ','22410') 
      ,(8,' ','22511') 
      ,(9,'P','27051') 
      ,(10,'C','22470') 
      ,(11,'C','22471') 
      ,(12,'C','22473') 
      ,(13,'C','22474') 
      ,(14,' ','22015') 
      ,(15,' ','22167') 
      ,(16,' ','12411') 
      ,(17,' ','22500') 
select t1.* 
    , case 
     when t1.type = 'C' 
      and t3.type = '' 
       then 'G' 
     when t1.type = 'P' or t1.type = 'C' 
      then 'G' 
     else 'N' 
    end [same_group] 
into #tmp2 
from #tmp t1 
    left join #tmp t2 on t1.line = t2.line + 1 
    left join #tmp t3 on t1.line = t3.line - 1 
order by t1.line 

select * 
    , case 
      when t.type <> '' 
       then (select max(line) 
        from #tmp2 
        where same_group = 'G' 
         and type = 'P' 
         and line <= t.line) 
     else t.line 
    end [group_id] 
from #tmp2 t 
order by line 

を現時点でそうする時間はありません。

+0

Thx。あなたはそれを簡略化することができます。 は 'トンをSELECT * 、CASE WHEN t.type <> '' THEN(@tmp FROM MAX(ライン) を選択WHEREタイプ<> '' およびType = 'P' AND line <= t.line) ELSE t.line END [グループ] FROM @tmp t' –

+0

@RetoE。クエリを簡素化するのに役立ちましたことを嬉しく思い、嬉しく思います。 –

2

入力が常に有効な場合は、次のクエリを使用できます。

SELECT *, RANK() OVER(ORDER BY gid) AS [group] 
FROM 
(
    SELECT *, SUM(CASE WHEN type = 'C' AND (prev = 'P' OR prev = 'C') THEN 0 ELSE 1 END) OVER(ORDER BY line) AS gid 
    FROM 
    (
     SELECT *, LAG(type) OVER(ORDER BY line) AS prev 
     FROM @tmp 
    ) AS withPreviouLine 
) AS grouped 

'P'が付いていない連続した 'C'は処理できません。 SQL SERVER 2012以降、LAGが追加されます。

+0

この投稿は次の言語に適用されます:2012 +で始まる – NEER

+0

SQL Server 2008 R2を使用しています。申し訳ありませんが、このソリューションをテストできません。 –

関連する問題