2017-04-25 13 views
0

私はSQL Server 2008で作業しています。テーブルからデータを抽出( "T")し、別のテーブルにDML(つまりINSERT INTO ... SELECT ... FROM ...構文)を使用して読み込む必要があります。表Tは、4つのレベルが定義された階層表です(レベル4が最も低く、レベル1が最も高い)。テーブルTの本質的なテーブル構造は以下の通りである:SQL階層テーブル:レベルをジャンプする方法

CREATE TABLE T 
(
    PK int 
    ,parentID int 
    ,level int 
    ,attribute1 varchar(255) 
    ,attribute2 varchar(255) 
    ,. 
    . 
    . 
    ,attributeN varchar(255) 
); 

すべての行(PK)はPARENTID介して上記レベルで正確に1行このテーブルマップに。私は効果的に私のSELECTのテーブルTを平らにする必要があります。つまり、所与のレベル4の行について、この行からいくつかの属性を選択し、対応するレベル2の親からの属性とそれに対応するレベル1の親からの属性を選択する必要があります。明らかに、JOINparent.PK = child.parentIDとすれば簡単にできます。ただし、レベル4の行ごとに「レベル3」の親が存在するとは限りません。これらの状況では、レベル4の行はレベル2の親に直接マッピングされます。それでも、すべての状況(レベル3の親が存在する場所と存在しない場所)で使用できるDMLテンプレートを1つだけ作成する必要があります。これどうやってするの?私のベースのクエリ(私が間違っている知っている)である:LEVEL3エントリが見つからない場合

SELECT 
    level4.attribute1 
    ,level2.attributeN 
    ,level1.attribute2 
FROM 
    T AS level4 
INNER JOIN 
    T AS level3 
ON 
    level3.PK = level4.parentID 
INNER JOIN 
    T AS level2 
ON 
    level2.PK = level3.parentID 
INNER JOIN 
    T AS level1 
ON 
    level1.PK = level2.parentID 
WHERE 
    level4.PK = 100 
; 
+1

ここで苦労しているのは、テーブルに正規化がないためです。アトリビュート1、アトリビュート2などは繰り返しグループと呼ばれ、1NFに違反します。あなたが持っているべきものは、このようなネスティングを可能にするアーキテクチャです。隣接リストはこれを処理する最も一般的な方法ですが、ネストされたセットはさらに優れています。または、hierarchyidデータ型もあります。どのような場合でも、ddl、サンプルデータ、および望ましい出力を提供する必要があります。ここから始めましょう。 http://spaghettidba.com/2015/04/24/how-to-post-a-t-sql-question-on-a-public-forum/ –

答えて

0

私はあなたの内部結合を集めるには失敗し、それが唯一のケースで動作しますので、あなたは、内側には、レベル2にLEVEL4に参加することはできませんここでlevel3の項目はありません。 2つのクエリのUNIONが可能です。別の可能性は、レベル2およびレベル1への2つの可能なパスを通してあなたの方法を参加左に次のようになります。

SELECT level4.attribute1, level2.attributeN, altlevel2.attributeN, level1.attribute2, altlevel1.attribute2 
FROM T AS level4 
LEFT JOIN T AS level3 ON level3.PK = level4.parentID 
LEFT JOIN T AS level2 ON level2.PK = level3.parentID 
LEFT JOIN T AS level1 ON level1.PK = level2.parentID 
LEFT JOIN T AS altlevel2 ON level2.PK = level4.parentID 
LEFT JOIN T AS altlevel1 ON level1.PK = level2.parentID 
WHERE level4.PK = 100; 

選択リストは、現在の属性の2つの可能性のあるセットが含まれています。指定されたレコードに対して、属性の1つのセットはnullになります。 CASEまたはCOALESCEを使用して、それらを表示したいどのような形式の属性でも選択リストに表示することができます。

0

レベル1は階層の最上位で親IDに依存しないため、元のテーブルを作成してその上に左ジョインを実行します。レベルの1つが欠落している場合、内部結合は階層全体を除外するため、左結合を使用します。結果のデータセットでレベルがスキップされないように、各レベルのwhere句を使用します。さもなければ、それはparentIDレベル1にスキップしたので、レベル2の列でレベル3に終わる可能性があります。結果のクエリがここにあります。

DECLARE @T TABLE (
PK INT 
,parentID int 
,level int 
,attribute1 varchar(255) 
,attribute2 varchar(255) 
) 

INSERT @T VALUES 
(1,0,1,'level1','1') 
,(2,0,1,'level1','2') 
,(3,0,1,'level1','3') 
,(4,1,2,'level2','1') 
,(5,2,2,'level2','2') 
,(6,2,2,'level2','3') 
,(7,4,3,'level3','1') 
,(8,5,3,'level3','2') 
,(9,6,3,'level3','3') 
,(10,3,3,'level3','4') 
,(11,9,4,'level4','1') 
,(12,10,4,'level4','2') 


SELECT 
    level1.PK AS L1_PK 
    ,level1.attribute1 AS L1_Attribute1 
    ,level1.attribute2 AS L1_Attribute2 
    ,level2.PK AS L2_PK 
    ,level2.attribute1 AS L2_Attribute1 
    ,level2.attribute2 AS L2_Attribute2 
    ,level3.PK AS L3_PK 
    ,level3.attribute1 AS L3_Attribute1 
    ,level3.attribute2 AS L3_Attribute2 
    ,level4.PK AS L4_PK 
    ,level4.attribute1 AS L4_Attribute1 
    ,level4.attribute2 AS L4_Attribute2 
FROM @T AS level1 
LEFT JOIN @T AS level2 ON 
    level1.PK = level2.parentID 
    AND level2.level = 2 
LEFT JOIN @T AS level3 ON 
    (level2.PK = level3.parentID 
    OR level1.PK = level3.parentID) 
    AND level3.level = 3 
LEFT JOIN @T AS level4 ON 
    (level3.PK = level4.parentID 
    OR level2.PK = level4.parentID 
    OR level1.PK = level4.parentID) 
    AND level4.level = 4 
WHERE level1.level = 1 
関連する問題