特定の方法で、ツリーの順序付けられた階層を取得する必要があります。問題のテーブルは、このように見えます(すべてのIDフィールドはuniqueidentifiersです。例のためにデータを単純化しました)。
EstimateItemID EstimateID ParentEstimateItemID ItemType -------------- ---------- ----------------- --- -------- 1 NULL製品 2 A 1製品 3 A 2サービス 4 NULL製品 5 A 4製品 6 A 5サービス 7 A 1サービス 8 A 4製品
ツリー構造のグラフィカルビュー(*は「サービス」を示します):
A ___/\ ___ /\ 1 4 /\/\ 2 7 * 5 8 // 3* 6 *
このクエリを使用して、階層を取得できます(「A」は一意の識別子であると偽装しますが、実際には存在しないことがわかります)。
DECLARE @EstimateID uniqueidentifier
SELECT @EstimateID = 'A'
;WITH temp as(
SELECT * FROM EstimateItem
WHERE EstimateID = @EstimateID
UNION ALL
SELECT ei.* FROM EstimateItem ei
INNER JOIN temp x ON ei.ParentEstimateItemID = x.EstimateItemID
)
SELECT * FROM temp
これにより、EstimateID 'A'の子がテーブルに表示される順序で表示されます。すなわち:
EstimateItemID -------------- 1 2 3 4 5 6 7 8
残念ながら、必要なのは、次の制約に従う結果セットを持つ順序付けられた階層です。
1。各ブランチはグループ化する必要があります 2。 ItemTypeが 'product'で、親が最上位のレコードは 3です。最上位ノード の後にグループ化されたItemType 'product'および非NULLの親を持つレコード。 ItemTypeが 'service'のレコードは、ブランチの最下位ノードです。
したがって、この例では、結果が必要な順序は次のとおりです。
EstimateItemID -------------- 1 2 3 7 4 5 8 6
これを達成するには、クエリに何を追加する必要がありますか?
これを試して:
;WITH items AS (
SELECT EstimateItemID, ItemType
, 0 AS Level
, CAST(EstimateItemID AS VARCHAR(255)) AS Path
FROM EstimateItem
WHERE ParentEstimateItemID IS NULL AND EstimateID = @EstimateID
UNION ALL
SELECT i.EstimateItemID, i.ItemType
, Level + 1
, CAST(Path + '.' + CAST(i.EstimateItemID AS VARCHAR(255)) AS VARCHAR(255))
FROM EstimateItem i
INNER JOIN items itms ON itms.EstimateItemID = i.ParentEstimateItemID
)
SELECT * FROM items ORDER BY Path
Path
を使用-親ノードでソートされた行a
各レベルでItemType
で子ノードを並べ替える場合は、Level
列のSUBSTRING
およびPath
で遊ぶことができます。..
ここ SQLFiddle サンプルデータ
これは、上からのファビオの素晴らしいアイデアへのアドオンです。私が彼の元の投稿への返信で言ったように。他の人がフォローしやすいように、より一般的なデータ、テーブル名、およびフィールドを使用して彼のアイデアを再投稿しました。
ありがとう、ファビオ!ところで偉大な名前。
最初に使用するいくつかのデータ:
CREATE TABLE tblLocations (ID INT IDENTITY(1,1), Code VARCHAR(1), ParentID INT, Name VARCHAR(20));
INSERT INTO tblLocations (Code, ParentID, Name) VALUES
('A', NULL, 'West'),
('A', 1, 'WA'),
('A', 2, 'Seattle'),
('A', NULL, 'East'),
('A', 4, 'NY'),
('A', 5, 'New York'),
('A', 1, 'NV'),
('A', 7, 'Las Vegas'),
('A', 2, 'Vancouver'),
('A', 4, 'FL'),
('A', 5, 'Buffalo'),
('A', 1, 'CA'),
('A', 10, 'Miami'),
('A', 12, 'Los Angeles'),
('A', 7, 'Reno'),
('A', 12, 'San Francisco'),
('A', 10, 'Orlando'),
('A', 12, 'Sacramento');
再帰クエリ:
-- Note: The 'Code' field isn't used, but you could add it to display more info.
;WITH MyCTE AS (
SELECT ID, Name, 0 AS TreeLevel, CAST(ID AS VARCHAR(255)) AS TreePath
FROM tblLocations T1
WHERE ParentID IS NULL
UNION ALL
SELECT T2.ID, T2.Name, TreeLevel + 1, CAST(TreePath + '.' + CAST(T2.ID AS VARCHAR(255)) AS VARCHAR(255)) AS TreePath
FROM tblLocations T2
INNER JOIN MyCTE itms ON itms.ID = T2.ParentID
)
-- Note: The 'replicate' function is not needed. Added it to give a visual of the results.
SELECT ID, Replicate('.', TreeLevel * 4)+Name 'Name', TreeLevel, TreePath
FROM MyCTE
ORDER BY TreePath;
CTEの結果に以下を追加する必要があると思います...
それらが出力に存在する場合、クエリの出力を別のCTEまたはクエリのFROM句として使用できるはずです。 BranchID、ItemTypeID、Parentで並べ替えます。