Условный оператор выбора SQL - PullRequest
1 голос
/ 17 января 2012

У меня есть таблица «Категории».Каждая строка имеет «CategoryId» (обязательно) и «ParentCategoryId» (не обязательно).Это позволяет установить отношения Родитель -> Дочерние между категориями.

Я пытаюсь выбрать все категории, но если существуют родительские -> дочерние отношения, выберите только родитель.

Вот то, что я сейчас пытаюсь, но это занимает вечность, и это совершенно неверно.Отказ от ответственности, 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

Ответы [ 4 ]

2 голосов
/ 17 января 2012

Следующий выбор извлекает все Категории, которые являются родителями по крайней мере для одной другой Категории:

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 голосов
/ 17 января 2012

В этом списке будут перечислены все родители, у которых есть дети. Родители без детей не будут отображаться.

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 голосов
/ 17 января 2012
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 голосов
/ 17 января 2012

Должно быть довольно просто:

select categoryid,categoryname,projectid,parentcategoryid,sortorder 
  from dbo.ProjectCategories
 where parentcategoryid is null
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...