查询列出所有分层的父母和兄弟姐妹及其孩子,但不列出自己的孩子

Posted

技术标签:

【中文标题】查询列出所有分层的父母和兄弟姐妹及其孩子,但不列出自己的孩子【英文标题】:Query to List all hierarchical parents and siblings and their childrens, but not list own childrens 【发布时间】:2014-04-22 06:29:44 【问题描述】:

我有一个基本的 SQL 表,每行之间有一个简单的层次结构连接。也就是说,每一行都有一个 ParentID,并使用它与另一行连接。如下

AccountID  |  AccountName  |  ParentID
---------------------------------------
    1            Mathew        0
    2            Philip        1
    3            John          2
    4            Susan         2
    5            Anita         1
    6            Aimy          1
    7            Elsa          3
    8            Anna          7
    .............................
.................................
    45           Kristoff      8

希望结构清晰

但我列出这些的要求有点奇怪。也就是说,当我们传递一个 AccountID 时,它应该列出它的所有父母和兄弟姐妹以及孩子的兄弟姐妹。但它永远不会将该 AccountID 的任何子项列出到任何级别。我可以用一张图片更详细地解释一下。抱歉图片的清晰度..我的是旧手机摄像头..

当我们传递 AccountID 4 时,它应该列出所有父母及其兄弟姐妹,但它不应该列出 4、6、7、8、9、10。这意味着应在结果中避免帐户及其任何子项(基于图片树元素)。希望解释清楚。

【问题讨论】:

还应该显示 5,11,12,... - 没有 4,6,7,8,9,10 的整个表吗?还是只有 4 - 2,1 的父母? @valex 是的.. 正是.. 我提到的就是它的兄弟姐妹和他们的孩子以及它的所有父母.. 【参考方案1】:

如果我做对了,并且您需要输出除 4 之外的整个表及其所有后代,请尝试以下递归查询:

WITH CT AS 
(
  SELECT * FROM T WHERE AccountID=4
  UNION ALL
  SELECT T.* FROM T 
     JOIN CT ON T.ParentID = CT.AccountId
)
SELECT * FROM T WHERE AccountID 
                NOT IN (SELECT AccountID FROM CT)

SQLFiddle demo

回答评论中的问题:

所以它不会遍历到顶部。它只遍历到指定 帐户。例如,如果我将 4 作为第一个参数,将 2 作为第二个参数 参数,结果应该是这些值 2,5,11,12

您应该从 ID=2 开始,一直到底部排除 ID=4,以便在 ID=4 之后切割整个子树:

WITH CT AS 
(
  SELECT * FROM T WHERE AccountID=2
  UNION ALL
  SELECT T.* FROM T 
     JOIN CT ON T.ParentID = CT.AccountId
  WHERE T.AccountId<>4
)

SELECT * FROM CT 

【讨论】:

对不起.. 如果您不介意,我需要更多支持。我们如何修改查询,使其不会从第二个参数向上移动。所以它不会遍历到顶部。它只遍历指定的帐户。例如,如果我将 4 作为第一个参数,将 2 作为第二个参数,则结果应该是这些值 2,5,11,12【参考方案2】:

试试这个:

;with cte as
(select accountid,parentid, 0 as level from tbl
 where parentid = 0
 union all
 select t.accountid,t.parentid,(level+1) from 
 cte c inner join tbl t on c.accountid= t.parentid
)
select * from cte
where level < (select level from cte where accountid = @accountid)

当您传入参数@accountid 时,这将返回参数之前级别上所有节点的accountid 值。

如果您想返回与输入相同级别的所有内容,除了输入本身,您可以将where 子句更改为;

where level <=(select level from cte where accountid= @accountid ) 
and accountid <> @accountid

在您的示例中,如果 @accountid = 4,这将返回值 1、2、3(祖先)以及 5、13、14(兄弟)。

【讨论】:

【参考方案3】:

这会返回你所追求的吗?

declare @AccountID int
set @AccountID = 4

;with parents
as (

    select AccountID, AccountName, ParentID
    from Account
    where AccountID = (select ParentID from Account Where AccountID = @AccountID)

    union all

    select A.AccountID, A.AccountName, A.ParentID
    from Account as A
    join parents as P
        on P.ParentID = A.AccountID
    ),
children
as (
    select AccountID, AccountName, ParentID
    from parents

    union all

    select A.AccountID, A.AccountName, A.ParentID
    from Account as A
    join children as C
        on C.AccountID = A.ParentID
    where A.AccountID <> @AccountID
    )
select distinct AccountID, AccountName, ParentID
from children
order by AccountID

【讨论】:

【参考方案4】:

对我来说,听起来你想上树。所以考虑到这个测试数据

DECLARE @tbl TABLE(AccountID INT,AccountName VARCHAR(100),ParentID INT)
INSERT INTO @tbl
VALUES
(1,'Mathew',0),
(2,'Philip',1),
(3,'John',2),
(4,'Susan',2),
(5,'Anita',1),
(6,'Aimy',1),
(7,'Elsa',3),
(8,'Anna',7)

我会这样写一个查询:

DECLARE @AcountID INT=4

;WITH CTE
AS
(
    SELECT
        tbl.AccountID,
        tbl.AccountName,
        tbl.ParentID
    FROM
        @tbl AS tbl
    WHERE
        tbl.AccountID=@AcountID
    UNION ALL
    SELECT
        tbl.AccountID,
        tbl.AccountName,
        tbl.ParentID
    FROM
        @tbl AS tbl
    JOIN CTE
        ON CTE.ParentID=tbl.AccountID
)
SELECT
    *
FROM
    CTE
WHERE
    NOT CTE.AccountID=@AcountID

这将返回如下结果:

2   Philip  1
1   Mathew  0

【讨论】:

以上是关于查询列出所有分层的父母和兄弟姐妹及其孩子,但不列出自己的孩子的主要内容,如果未能解决你的问题,请参考以下文章

查找父母的上一个兄弟姐妹的孩子(其中任何一个)是不是包含特定文本

在 Python 的 Playwright 中,我如何获取与 ElementHandle 相关的元素(孩子、父母、祖父母、兄弟姐妹)?

php 而不是列出当前页面的所有子孙的wp_list_pages,此方法列出了父页面,兄弟姐妹

XCTest 中查询的父母和兄弟姐妹(UI 测试)

jQuery选择除self之外的所有兄弟姐妹和孩子

Flutter - 当兄弟姐妹灵活时,扩展不会占用所有可用空间