2016-04-22 5 views
5

これでは苦労しています。私は、親を与えられた自己参照表からすべての子レコードを取得する方法と、子レコードの親を取得する方法まで、いくつかの例を見てきました。すべての階層レベルを選択してください。SQL Server

私がしようとしているのは、IDを指定してレコードとすべての子レコードを返すことです。

これをコンテキストにするには、私は企業階層を持っています。

#Role  Level# 
-------------------- 
Corporate   0 
Region   1 
District   2 
Rep    3 

は私が必要なのは(1)レコードが何であるかをレベル割り出し及び(2)そのレコードとすべての子レコードを取得手順である:ここで。

地区というアイデアは、地区内のすべての地区と担当者が見ることができます。地区は担当者を見ることができます。啓示は自分自身しか見ることができません。

私はテーブルがあります。

ID   ParentId   Name 
------------------------------------------------------- 
1    Null    Corporate HQ 
2    1     South Region 
3    1     North Region 
4    1     East Region 
5    1     West Region 
6    3     Chicago District 
7    3     Milwaukee District 
8    3     Minneapolis District 
9    6     Gold Coast Dealer 
10   6     Blue Island Dealer 

私はこれをどのように行うのです。たとえば、@id = 3の予想結果を

CREATE PROCEDURE GetPositions 
    @id int 
AS 
BEGIN 
    --What is the most efficient way to do this-- 
END 
GO 

を、私は返すようにしたいでしょう:

3, 6, 7, 8, 9, 10 

私はこれに関する助けやアイデアをありがとうと思います。あなたは再帰CTEを経由してこれを行うことができます

+1

期待される結果は何でしょうか? –

+0

私は期待される結果を示すために質問を更新しました。 – JDBennett

答えて

6

:あなたは少しでhierarchyid型のデータ型を使用することができ、SQL Serverの合理的に現代版にしていると仮定すると

DECLARE @id INT = 3; 

WITH rCTE AS(
    SELECT *, 0 AS Level FROM tbl WHERE Id = @id 
    UNION ALL 
    SELECT t.*, r.Level + 1 AS Level 
    FROM tbl t 
    INNER JOIN rCTE r 
     ON t.ParentId = r.ID 
) 
SELECT * FROM rCTE OPTION(MAXRECURSION 0); 

ONLINE DEMO

+0

それは完璧です!好奇心の外に - 大量のレコードに対してこれはうまくいくでしょうか?私。 50K +のレコードがあり、Idは企業(上位)の親です。これはどのようにして保持されますか? – JDBennett

+0

一般に、再帰的なCTEは大きなテーブルではうまくスケールされません。すべてと同様に、テスト! –

0

肘グリースのビット。まず、セットアップ:これは階層を表し1つの計算列を持つだけで泥沼の標準的な再帰テーブル式で

with cte as (
    select *, cast(concat('/', ID, '/') as varchar(max)) as [path] 
    from [dbo].[yourTable] 
    where [ParentID] is null 

    union all 

    select child.*, 
     cast(concat(parent.path, child.ID, '/') as varchar(max)) as [path] 
    from [dbo].[yourTable] as child 
    join cte as parent 
     on child.ParentID = parent.ID 
) 
update t 
set path = c.path 
from [dbo].[yourTable] as t 
join cte as c 
    on t.ID = c.ID; 

alter table [dbo].[yourTable] add [path] hierarchyid null; 

次に、私たちは、新しい列を移入ます。それは難しい部分です。さて、あなたの手順は、次のようなものを見ることができます:

create procedure dbo.GetPositions (@id int) as 
begin 
    declare @h hierarchyid 
    set @h = (select Path from [dbo].[yourTable] where ID = @id); 

    select ID, ParentID, Name 
    from [dbo].[yourTable] 
    where Path.IsDescendentOf(@h) = 1; 
end 

だから、あなたがそれを計算する必要がないように、あなたはhierarchyid型でやっているすべては、与えられた行の系譜を記憶しているラップします選択した時間に飛ぶ。

関連する問題