【问题标题】:Conditional SQL Select Statement条件 SQL 选择语句
【发布时间】:2012-01-16 20:38:19
【问题描述】:

我有一个“类别”表。每行都有一个“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

【问题讨论】:

  • 我闻到了递归 CTE 的味道。如果别人不先做,我回家后会做。
  • 如果您的 parent->child 层次结构中有多个级别,您是否只想为每个孩子提供最低级别的父级?
  • 请考虑选择正确的答案

标签: .net sql sql-server sql-server-2008 tsql


【解决方案1】:

以下选择检索至少一个其他类别的父类别的所有类别:

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

【讨论】:

  • 如果有多个父/子关系怎么办?
  • @DanAndrews 感谢您注意到这一点。我只是添加了distinct 关键字以避免在这种情况下重复记录。
【解决方案2】:

应该相当简单:

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

【讨论】:

  • 经过进一步审查,我认为这就是答案。没有父母的孩子的 parentcategoryID = null。顶级父母的 parentCategoryID = null。所有其他人都不会。
  • 是的,在我重新阅读了你的问题之后,确实就是这么简单,但是你要确保有一个孩子......所以会有一个内部连接。我会附加我的答案,但它可能已经在另一个答案中完成了。
【解决方案3】:
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 参数。

一个更安全的版本,在父类别的某些列为 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 

【讨论】:

    【解决方案4】:

    这将列出所有有孩子的父母。不会显示没有孩子的父母。

    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
    

    【讨论】:

    • 唉,他真正想要的只是父母。
    猜你喜欢
    • 1970-01-01
    • 2013-10-04
    • 1970-01-01
    • 2014-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-09
    相关资源
    最近更新 更多