私は階層を表すこのテーブルを持っています:
childID parentID NAME siblingOrder
1 1 a 0
212 1 ab 1
112 1 ac 2
412 1 ad 3
-912 112 aca 0
構造は次のとおりです。
a
+----ab
+----ac
+---aca
+----ad
(siblingOrder
columnは、ab
、ac
、ad
の順序を制御するためのものです)
私はすでにsiblingOrder
を使用するこのソリューションを持っています:
;WITH CTE AS(
SELECT childID, parentID, 0 AS depth, NAME , siblingOrder,
CAST(RIGHT('00000' + CAST(siblingOrder AS VARCHAR(6)), 6) AS VARCHAR(1024)) AS PATH
FROM @myTable
WHERE childID = parentID
UNION ALL
SELECT TBL.childID, TBL.parentID,
CTE.depth + 1 , TBL.name ,TBL.siblingOrder,
CAST(cte.Path + '.' + RIGHT('00000' + CAST(Tbl.siblingOrder AS VARCHAR(6)), 6)AS VARCHAR(1024) )
FROM @myTable AS TBL
INNER JOIN CTE ON TBL.parentID = CTE.childID
WHERE TBL.childID<>TBL.parentID
)
SELECT path,depth, childID, parentID, siblingOrder, REPLICATE('----', depth) + name
FROM CTE
ORDER BY PATH
したがって、order by
PATH
は実際に仕事をします:
問題:
問題は、IMust(!)が機能するためにsiblingOrder
に値を入力することです!
それ以外の場合、例:
すべてのsiblingOrder
に0
を入れると、次のようになります。
(はい、パスでソートするようになりました-機能しません...)
aca
が常にac
の下にある必要があります
(私がsiblingOrder
を追加した唯一の理由は兄弟を注文することです!)そして私は必要のないときにsiblingOrder
を追加することを強制したくありません
質問:
siblingOrder
が兄弟にのみ影響するようにクエリを拡張することは可能ですか?
つまり、兄弟の順序を気にしない場合(0
を入力することにより)、aca
がac
の下にあることを期待します。
パスにparentID
とchildID
を含める必要があります。だから代わりに
RIGHT('00000' + CAST(Tbl.siblingOrder AS VARCHAR(6)), 6)
あなたは書くべきです
RIGHT('0000000000' + CAST(Tbl.parentID AS VARCHAR(10)), 10) + RIGHT('00000' + CAST(Tbl.siblingOrder AS VARCHAR(6)), 6) + RIGHT('0000000000' + CAST(Tbl.childID AS VARCHAR(10)), 10)
(それはあなたのコードの2つの場所にあります)
このように使用すると、必要に応じてsiblingOrderを指定できます。存在する場合、子の順序を上書きします。存在しない場合、子供はchildIDで注文されます。
SQL Fiddle siblingOrderなし
MS SQL Server 2008スキーマセットアップ:
CREATE TABLE dbo.MyTable
([childID] int, [parentID] int, [NAME] varchar(3), [siblingOrder] int)
;
INSERT INTO dbo.MyTable
([childID], [parentID], [NAME], [siblingOrder])
VALUES
(1, 1, 'a', 0),
(212, 1, 'ab', 0),
(112, 1, 'ac', 0),
(412, 1, 'ad', 0),
(-912, 112, 'aca', 0)
;
クエリ1:
;WITH CTE AS(
SELECT childID, parentID, 0 AS depth, NAME , siblingOrder,
CAST(RIGHT('0000000000' + CAST(parentID AS VARCHAR(10)), 10) + RIGHT('00000' + CAST(siblingOrder AS VARCHAR(6)), 6)+ RIGHT('0000000000' + CAST(childID AS VARCHAR(10)), 10) AS VARCHAR(1024)) AS PATH
FROM dbo.MyTable
WHERE childID = parentID
UNION ALL
SELECT TBL.childID, TBL.parentID,
CTE.depth + 1 , TBL.name ,TBL.siblingOrder,
CAST(cte.Path + '.' + RIGHT('0000000000' + CAST(Tbl.parentID AS VARCHAR(10)), 10) + RIGHT('00000' + CAST(Tbl.siblingOrder AS VARCHAR(6)), 6)+ RIGHT('0000000000' + CAST(Tbl.childID AS VARCHAR(10)), 10) AS VARCHAR(1024) )
FROM dbo.MyTable AS TBL
INNER JOIN CTE ON TBL.parentID = CTE.childID
WHERE TBL.childID<>TBL.parentID
)
SELECT path,depth, childID, parentID, siblingOrder, REPLICATE('----', depth) + name
FROM CTE
ORDER BY PATH
結果:
| PATH | DEPTH | CHILDID | PARENTID | SIBLINGORDER | COLUMN_5 |
----------------------------------------------------------------------------------------------------------------------------------------------
| 00000000010000000000000001 | 0 | 1 | 1 | 0 | a |
| 00000000010000000000000001.00000000010000000000000112 | 1 | 112 | 1 | 0 | ----ac |
| 00000000010000000000000001.00000000010000000000000112.0000000112000000000000-912 | 2 | -912 | 112 | 0 | --------aca |
| 00000000010000000000000001.00000000010000000000000212 | 1 | 212 | 1 | 0 | ----ab |
| 00000000010000000000000001.00000000010000000000000412 | 1 | 412 | 1 | 0 | ----ad |
SQL Fiddle with siblingOrder
MS SQL Server 2008スキーマセットアップ:
CREATE TABLE dbo.MyTable
([childID] int, [parentID] int, [NAME] varchar(3), [siblingOrder] int)
;
INSERT INTO dbo.MyTable
([childID], [parentID], [NAME], [siblingOrder])
VALUES
(1, 1, 'a', 0),
(212, 1, 'ab', 1),
(112, 1, 'ac', 3),
(412, 1, 'ad', 2),
(-912, 112, 'aca', 0)
;
クエリ1:
;WITH CTE AS(
SELECT childID, parentID, 0 AS depth, NAME , siblingOrder,
CAST(RIGHT('0000000000' + CAST(parentID AS VARCHAR(10)), 10) + RIGHT('00000' + CAST(siblingOrder AS VARCHAR(6)), 6)+ RIGHT('0000000000' + CAST(childID AS VARCHAR(10)), 10) AS VARCHAR(1024)) AS PATH
FROM dbo.MyTable
WHERE childID = parentID
UNION ALL
SELECT TBL.childID, TBL.parentID,
CTE.depth + 1 , TBL.name ,TBL.siblingOrder,
CAST(cte.Path + '.' + RIGHT('0000000000' + CAST(Tbl.parentID AS VARCHAR(10)), 10) + RIGHT('00000' + CAST(Tbl.siblingOrder AS VARCHAR(6)), 6)+ RIGHT('0000000000' + CAST(Tbl.childID AS VARCHAR(10)), 10) AS VARCHAR(1024) )
FROM dbo.MyTable AS TBL
INNER JOIN CTE ON TBL.parentID = CTE.childID
WHERE TBL.childID<>TBL.parentID
)
SELECT path,depth, childID, parentID, siblingOrder, REPLICATE('----', depth) + name
FROM CTE
ORDER BY PATH
結果:
| PATH | DEPTH | CHILDID | PARENTID | SIBLINGORDER | COLUMN_5 |
----------------------------------------------------------------------------------------------------------------------------------------------
| 00000000010000000000000001 | 0 | 1 | 1 | 0 | a |
| 00000000010000000000000001.00000000010000010000000212 | 1 | 212 | 1 | 1 | ----ab |
| 00000000010000000000000001.00000000010000020000000412 | 1 | 412 | 1 | 2 | ----ad |
| 00000000010000000000000001.00000000010000030000000112 | 1 | 112 | 1 | 3 | ----ac |
| 00000000010000000000000001.00000000010000030000000112.0000000112000000000000-912 | 2 | -912 | 112 | 0 | --------aca |