查询列出所有分层的父母和兄弟姐妹及其孩子,但不列出自己的孩子
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 相关的元素(孩子、父母、祖父母、兄弟姐妹)?