Sql 如何从同一分层表中的一个值(可能是父值,也可能是子值)获取父级和子级?

Sql 如何从同一分层表中的一个值(可能是父值,也可能是子值)获取父级和子级?,sql,sql-server,tsql,Sql,Sql Server,Tsql,考虑下表: 表格:类别 CategoryID int identity PK <--. ParentID int NULL FK --->-----' Name varchar(50) ProjectID int PK FK CategoryID int PK FK ProjectID CategoryID -------------------------------- 1 2 <-- Either a parent or child cate

考虑下表:

表格:类别

CategoryID int identity PK <--.
ParentID int NULL FK --->-----'
Name varchar(50)
ProjectID int PK FK
CategoryID int PK FK

ProjectID    CategoryID
--------------------------------
1            2 <-- Either a parent or child category
表格:项目

ProjectID int identity PK
Name varchar(50) NOT NULL
我还有一个项目和类别的连接表

表格:项目类别

CategoryID int identity PK <--.
ParentID int NULL FK --->-----'
Name varchar(50)
ProjectID int PK FK
CategoryID int PK FK

ProjectID    CategoryID
--------------------------------
1            2 <-- Either a parent or child category
所以问题是,我不确定为应用程序提供这两者的最佳方式,但它需要在一个SQL查询中完成,该查询将生成一行数据

更新


我给自己贴了一个答案,但如果有更好的方法,请把它撕成碎片。

我可能已经找到了自己的答案,但如果有更好的方法,我会很快选择一个更好的答案

SELECT p.*
      ,ISNULL(cat.ParentID, cat.CategoryID) AS ParentCategoryID
      ,CASE WHEN cat.ParentID IS NOT NULL THEN cat.CategoryID
       END ChildCategoryID

FROM Project p
OUTER APPLY (
    SELECT TOP 1 c.CategoryID, c.ParentID FROM ProjectCategory pc
    INNER JOIN Category c ON c.CategoryID = pc.CategoryID
    WHERE pc.ProjectID = p.ProjectID
) cat

我假设类别表上从ParentID到CategoryID有自引用外键。在您的描述中,您确实使事情复杂化了,因为ParentID也将作为CategoryID存在,所以您只需要在两个表之间进行简单的连接:

select pc.ProjectID,
       coalesce(c.ParentID, c.CategoryID) as ParentCategoryID --shows category id as parent if it has no parent
       case when c.ParentID is not null then c.CategoryID end as ChildCategoryID
from   ProjectCategory as pc
inner  join Category as c
on     c.CategoryID = pc.CategoryID

不可能有孙子或更深层次的亲子关系吗?基本上没有,还没有。应用程序的解释是现在强制执行的,但由于此规则将来可能会更改,因此我在DB中以这种方式设置它。@Anand,为了简化,我更新了我的问题。感谢您花时间提供帮助。在您的示例中,如果c.ParentID为null,则此操作似乎失败。如果不是ParentID,我需要获取ParentID。请将我的答案作为我使用
ISNULL()
的示例。我肯定有可能把事情搞得太复杂了。我将更新我的问题,并尝试清除一些垃圾。谢谢@Anand的帮助。我想你的意思是,如果没有父类,它应该将类别显示为它自己的父类?如果是的话,编辑答案以反映这一点。是的,这就是我的意思。我盯着这个看了之后,脑子都被搞糊涂了。不过,您仍然需要处理
ChildCategoryID
,对吗?就像我的回答一样?否则,
ChildCategoryID
实际上可能是一个父类。除此之外,区别似乎是连接与外部应用。我不是SQL性能测试方面的专家。我的例子中的前1个是多余的。在测试时,我的数据有点乱。哈哈,你让自己更加困惑:)如果子类别是父类别,那么它将作为父类别显示在子类别的行中。
select pc.ProjectID,
       coalesce(c.ParentID, c.CategoryID) as ParentCategoryID --shows category id as parent if it has no parent
       case when c.ParentID is not null then c.CategoryID end as ChildCategoryID
from   ProjectCategory as pc
inner  join Category as c
on     c.CategoryID = pc.CategoryID