2012-01-16 27 views
1

私は 'Categories'テーブルを持っています。各行には 'CategoryId'(必須)と 'ParentCategoryId'(必須ではない)があります。これにより、カテゴリ間の親 - >子関係が可能になります。条件付きSQL Selectステートメント

私がしようとしているのはすべてのカテゴリを選択することですが、親 - 子関係が存在する場合は、親のみを選択してください。

私は現在、私が現在試みていることはありますが、それは永遠に奪われており、間違っています。免責事項、SQLは私の強い訴訟ではありません!

declare @ProjectId int 
set @ProjectId = 1 

declare @catid int 
declare @catname nvarchar(100) 
declare @catprojid int 
declare @catparentid int 
declare @sortorder int 

declare db_cursor cursor for 
select categoryid,categoryname,projectid,parentcategoryid,sortorder from dbo.ProjectCategories 
where ProjectId = @ProjectId 

open db_cursor 
fetch NEXT from db_cursor into @catid,@catname,@catprojid,@catparentid,@sortorder 

while @@FETCH_STATUS = 0 
begin 
    if @catparentid != null select * from dbo.ProjectCategories where CategoryId = @catparentid 
    else select @catid,@catname,@catprojid,@catparentid,@sortorder 
end 

close db_cursor 
deallocate db_cursor 
go 
+2

再帰的なCTEの匂いがします。誰かがそれを最初にやっていないと私が家に帰ると、私はそれをやります。 – SQLMason

+1

カーソルを動かす! – JonH

+0

親 - >子階層に複数のレベルがある場合は、各子の最下位レベルの親だけを必要としますか? – JNK

答えて

2

次のselectを取り出し、少なくとも一つの他のカテゴリーに親であるすべてのカテゴリー:

declare @ProjectId int 
set @ProjectId = 1 

select distinct 
    parent.categoryid, 
    parent.categoryname, 
    parent.projectid, 
    parent.parentcategoryid, 
    parent.sortorder 
from dbo.ProjectCategories parent 
join dbo.ProjectCategories child on child.ParentCategoryId = parent.CategoryId 
where parent.ProjectId = @ProjectId 
+0

親子関係が複数ある場合はどうなりますか? – SQLMason

+0

@DanAndrewsそれに気づいてくれてありがとう。このケースで重複レコードを避けるために 'distinct'キーワードを追加しました。 – GolfWolf

0

はかなり簡単です:

select categoryid,categoryname,projectid,parentcategoryid,sortorder 
    from dbo.ProjectCategories 
where parentcategoryid is null 
+0

さらに検討すると、これは答えだと思います。親を持たない子供はparentcategoryID = nullになります。トップレベルの親はparentCategoryID = nullを持ちます。他のすべてはそうしないでしょう。 – Anderson

+0

ええ、あなたの質問を再読した後、それは本当にシンプルですが、子供がいることを確認したいので...内部結合があります。私は自分の答えを追加しますが、別の答えで既に行われているかもしれません。 – SQLMason

0
SELECT 
    COALESCE(parent.categoryid, child.categoryid), 
    COALESCE(parent.categoryname, child.categoryname), 
    COALESCE(parent.projectid, child.projectid), 
    COALESCE(parent.parentcategoryid, child.parentcategoryid), 
    COALESCE(parent.sortorder, child.sortorder) 
FROM 
    dbo.ProjectCategories child 
    LEFT JOIN dbo.ProjectCategories parent 
     ON child.parentcategoryid = parent.categoryid 
WHERE 
    child.ProjectId = @ProjectId 

COALESCEが最初に返します非NULLパラメータ。

やや安全なバージョンは、ケース内の親カテゴリの列の一部は、これは、子供を持つ親のすべてが一覧表示されます

SELECT 
    CASE WHEN parent.categoryid IS NULL THEN child.categoryid ELSE parent.categoryid END, 
    CASE WHEN parent.categoryid IS NULL THEN child.categoryname ELSE parent.categoryname END, 
    CASE WHEN parent.categoryid IS NULL THEN child.projectid ELSE parent.projectid END, 
    CASE WHEN parent.categoryid IS NULL THEN child.parentcategoryid ELSE parent.parentcategoryid END, 
    CASE WHEN parent.categoryid IS NULL THEN child.sortorder ELSE parent.sortorder END 
FROM 
    dbo.ProjectCategories child 
    LEFT JOIN dbo.ProjectCategories parent 
     ON child.parentcategoryid = parent.categoryid 
WHERE 
    child.ProjectId = @ProjectId 
0

NULLです。子供なしの保護者は表示されません。ここで

DECLARE @ProjectCategories TABLE 
(
    categoryid   INT, 
    categoryname  VARCHAR(10), 
    projectid   INT, 
    parentcategoryid INT, 
    sortorder   INT 
) 

INSERT INTO @ProjectCategories 
SELECT 1, 'Main1', 1, null, 1 UNION ALL 
SELECT 2, 'Child1', 1, 1,  1 UNION ALL 
SELECT 3, 'Child2', 1, 2,  1 UNION ALL 
SELECT 4, 'Child3', 1, 3,  1 UNION ALL 
SELECT 5, 'Child4', 1, 4,  1 UNION ALL 
SELECT 6, 'MainA', 2, null, 1 UNION ALL 
SELECT 7, 'ChildA', 2, 6,  1 UNION ALL 
SELECT 8, 'ChildB', 2, 7,  1 UNION ALL 
SELECT 9, 'Main!', 3, null, 1 

SELECT * 
FROM @ProjectCategories Child 
    INNER JOIN @ProjectCategories Parent 
     ON Child.parentcategoryid = Parent.categoryid 
      AND Parent.parentcategoryid IS NULL 

すべての親は関係なく、子供たちが存在する場合は、次のとおりです。

DECLARE @ProjectCategories TABLE 
(
    categoryid   INT, 
    categoryname  VARCHAR(10), 
    projectid   INT, 
    parentcategoryid INT, 
    sortorder   INT 
) 

INSERT INTO @ProjectCategories 
SELECT 1, 'Main1', 1, null, 1 UNION ALL 
SELECT 2, 'Child1', 1, 1,  1 UNION ALL 
SELECT 3, 'Child2', 1, 2,  1 UNION ALL 
SELECT 4, 'Child3', 1, 3,  1 UNION ALL 
SELECT 5, 'Child4', 1, 4,  1 UNION ALL 
SELECT 6, 'MainA', 2, null, 1 UNION ALL 
SELECT 7, 'ChildA', 2, 6,  1 UNION ALL 
SELECT 8, 'ChildB', 2, 7,  1 UNION ALL 
SELECT 9, 'Main!', 3, null, 1 

SELECT * 
FROM @ProjectCategories Parent 
WHERE Parent.parentcategoryid IS NULL 

はここに関係なく、そこにどのように多くの子供たちの親のための子供のすべてを取得しないであろう、再帰CTEです。

DECLARE @ProjectCategories TABLE 
(
    categoryid   INT, 
    categoryname  VARCHAR(10), 
    projectid   INT, 
    parentcategoryid INT, 
    sortorder   INT 
) 

INSERT INTO @ProjectCategories 
SELECT 1, 'Main1', 1, null, 1 UNION ALL 
SELECT 2, 'Child1', 1, 1,  1 UNION ALL 
SELECT 3, 'Child2', 1, 2,  1 UNION ALL 
SELECT 4, 'Child3', 1, 3,  1 UNION ALL 
SELECT 5, 'Child4', 1, 4,  1 UNION ALL 
SELECT 6, 'MainA', 2, null, 1 UNION ALL 
SELECT 7, 'ChildA', 2, 6,  1 UNION ALL 
SELECT 8, 'ChildB', 2, 7,  1 UNION ALL 
SELECT 9, 'Main!', 3, null, 1 


;WITH Projects 
(
    categoryid, 
    categoryname, 
    parentcategoryid 
) 
AS 
(
    -- Base Case 
    SELECT categoryid, 
      categoryname, 
      parentcategoryid 
    FROM @ProjectCategories 
    WHERE projectid = 1 -- Change this to 1, 2, or 3 
     AND parentcategoryid IS NULL 
    UNION ALL 
    -- Recursive 
    SELECT pc.categoryid, 
      pc.categoryname, 
      pc.parentcategoryid 
    from Projects 
     INNER JOIN @ProjectCategories pc 
      ON pc.parentcategoryid = Projects.categoryid 
) 
SELECT * from Projects 
+0

ああ、彼が本当に望むのは両親だ。 – SQLMason