2

1 つのアイテムの完全なツリー パスを提供する SQL クエリが必要です。テーブルは次のようになり、MyItem_MyItemId と MyItemMapping_MyItemId の間には 1:n の関係があります。

テーブル MyItem:

MyItem_MyItemId | MyItem_Title 
1 | Desktop
2 | Workspace
3 | Folder1
4 | Folder2
5 | Folder3
6 | Folder4
...

テーブル MyItemMapping:

MyItemMapping_MyItemId | MyItemMapping_MyItemParentId
4 | 3
3 | 2
2 | 1
1 | NULL
5 | 2
6 | 2
...

ここで、"Desktop\Workspace\Folder1\Folder2.

再帰クエリ (以下を参照) で試してみましたが、SQL Server が解決するのに約 10 秒かかります。データベースには 5000 レコードしかありません。このクエリを使用すると、5000 レコードすべてに対してパスが計算されることがわかりますが、必要なのは 1 つのアイテムだけです。誰でも私を助けることができますか?

WITH 
MyTable as
(
 select MyItem_MyItemId, MyItem_Title, MyItemMapping_MyItemParentId 
 from MyItem inner join MyItemMapping on MyItem_MyItemId = MyItemMapping_MyItemId
),
RecursiveTable AS 
(
  select t.MyItem_MyItemId, t.MyItem_Title, t.MyItemMapping_MyItemParentId
  from MyTable as t
  Where MyItemMapping_MyItemParentId is null 
  union all
  select  t.MyItem_MyItemId,  CAST(RecursiveTable.MyItem_Title + '\' + t.MyItem_Title AS NVARCHAR(max)), t.MyItemMapping_MyItemParentId
  from MyTable as t
  JOIN RecursiveTable ON RecursiveTable.MyItem_MyItemId = t.MyItemMapping_MyItemParentId
)   
select MyItem_Title from RecursiveTable where MyItem_MyItemid = 4

どうもありがとうございました。

よろしくお願いします。マルク

4

2 に答える 2

1

反対方向に移動します。必要な項目を選択したら、バックスラッシュで区切られた有効な値のリストを作成するためにFOR XML句でパターンを使用します。

DECLARE @MyItemMapping_MyItemId int = 4
;WITH cte AS
 (
  SELECT MyItemMapping_MyItemId, MyItemMapping_MyItemParentId, 1 AS rn
  FROM MyItemMapping
  Where MyItemMapping_MyItemId = @MyItemMapping_MyItemId 
  UNION ALL
  SELECT m.MyItemMapping_MyItemId, m.MyItemMapping_MyItemParentId, rn + 1
  FROM MyItemMapping m JOIN cte c ON c.MyItemMapping_MyItemParentId = m.MyItemMapping_MyItemId
  )
  SELECT STUFF((SELECT '/' + m.MyItem_Title                   
                FROM cte c JOIN MyItem m                 
                  ON c.MyItemMapping_MyItemId = m.MyItem_MyItemId
                ORDER BY c.rn DESC                    
                FOR XML PATH, TYPE).value('.[1]', 'nvarchar(max)'), 1, 1, '') AS pathFolder 

パスフォルダー

結果:

PathFolder

Desktop/Workspace/Folder1/Folder2

SQLFiddle のデモ

于 2013-03-23T16:02:02.977 に答える
0

クエリを確認してください:

declare @MyItem as table (MyItem_MyItemId INT, MyItem_Title nvarchar(50))

insert into @MyItem values 
(1, 'Desktop'),
(2, 'Workspace'),
(3, 'Folder1'),
(4, 'Folder2')

declare @MyItemMapping as table (MyItemMapping_MyItemId INT, MyItemMapping_MyItemParentId int)

insert into @MyItemMapping values
(4, 3),
(3, 2),
(2, 1),
(1, NULL)

select * From @MyItem
select * From @MyItemMapping

;WITH parent AS
(
    SELECT MyItemMapping_MyItemId, MyItemMapping_MyItemParentId, CAST( b.MyItem_Title as nvarchar(max))MyItem_Title
    from @MyItemMapping a INNER JOIN @MyItem b on a.MyItemMapping_MyItemId=b.MyItem_MyItemId
    WHERE MyItemMapping_MyItemParentId is NULL

    UNION ALL 
    SELECT t.MyItemMapping_MyItemId, t.MyItemMapping_MyItemParentId ,CAST( parent.MyItem_Title+'/'+ b.MyItem_Title as nvarchar(max))MyItem_Title
    FROM parent INNER JOIN @MyItemMapping t ON parent.MyItemMapping_MyItemId =  t.MyItemMapping_MyItemParentId
        INNER JOIN @MyItem b on t.MyItemMapping_MyItemId=b.MyItem_MyItemId
)

SELECT MyItem_Title FROM  parent where MyItemMapping_MyItemId=(select MAX(MyItem_MyItemId) from @MyItem)

また

declare @output varchar(max)
;WITH parent AS
(
    SELECT MyItemMapping_MyItemId, MyItemMapping_MyItemParentId
    from @MyItemMapping
    WHERE MyItemMapping_MyItemParentId is NULL

    UNION ALL 
    SELECT t.MyItemMapping_MyItemId, t.MyItemMapping_MyItemParentId 
    FROM parent INNER JOIN @MyItemMapping t ON parent.MyItemMapping_MyItemId =  t.MyItemMapping_MyItemParentId
)

SELECT @output = COALESCE(@output + '/', '')+ (select MyItem_Title from @MyItem where MyItem_MyItemId=MyItemMapping_MyItemId) 
FROM  parent where MyItemMapping_MyItemId <= 4 group by MyItemMapping_MyItemId order by MyItemMapping_MyItemId

select @output
于 2013-03-23T09:43:44.100 に答える