从父项列表中查找顶级父项的SQL

从父项列表中查找顶级父项的SQL,sql,Sql,我有两个表:表1有一列父ID的p-ID,表2有两列:p_ID和C-idChild ID 表2中显示了每个子级的父级,但子级可以有多个父级,反之亦然。多对多。现在,我需要找到所有的P-id,根据这个P-id | C|id关系,这些P-id表示没有父母的父母。在我看来,困难在于没有关于父级的直接信息 P_id ------ 1 2 3 C_id ------ 1 2 3 4 5 P_id C_id ----------- 1 1 1 2 1 3

我有两个表:表1有一列父ID的p-ID,表2有两列:p_ID和C-idChild ID

表2中显示了每个子级的父级,但子级可以有多个父级,反之亦然。多对多。现在,我需要找到所有的P-id,根据这个P-id | C|id关系,这些P-id表示没有父母的父母。在我看来,困难在于没有关于父级的直接信息

P_id
------
1
2
3

C_id
------
1 
2 
3 
4 
5

P_id   C_id
-----------
1      1  
1      2  
1      3   
2      1   
2      2   
2      3   
2      4   
3      1  
3      5  
3      3  
答案应该是p_id 2和3

SELECT p_id from TableA as A
WHERE NOT EXISTS (SELECT * FROM TableB as B
                  WHERE B.C_id = A.P_ID)
这将向您显示其ID在第二个表中未显示为子ID的所有家长

编辑:

试试这个

SELECT b1.p_id 
from #TableB as B1
WHERE c_id NOT IN ( SELECT c_id
                    FROM #TableB as b2
                    WHERE b2.p_id <> b1.p_id)
如果我想的没错,这应该会告诉你所有的家长id都有一个其他家长id都没有的孩子id

这将向您显示其ID在第二个表中未显示为子ID的所有家长

编辑:

试试这个

SELECT b1.p_id 
from #TableB as B1
WHERE c_id NOT IN ( SELECT c_id
                    FROM #TableB as b2
                    WHERE b2.p_id <> b1.p_id)

如果我想对了,这应该会告诉你所有的家长id都有一个孩子id,而其他家长id都没有。

我已经探讨了这个问题。根据您的需求,您应该将关系表视为一个表。你需要提升,直到你找到一条没有父母的路

这本质上是一个递归操作,因此您的SQL版本将在这里发挥作用

给定一个值,您可以找到父项或缺少,然后需要重新运行相同的测试以确定相同的内容。。。。一直到你找不到父母为止

您的情况是否限制嵌套层的数量?如果是这样的话,这可以在没有递归的情况下完成

更多讨论请参见我的问题:

编辑: 假设你有一个有限的嵌套深度3,你可以简单地重复加入以耗尽你的嵌套深度

SELECT 
    *
FROM 
    table a
LEFT OUTER JOIN table b 
    ON b.C_id = a.P_id
LEFT OUTER JOIN table c 
    ON c.C_id = b.P_id
LEFT OUTER JOIN table d 
    ON d.C_id = c.P_id
WHERE
    a.C_id = @pYourValue
    AND (
        a.P_id IS NULL 
        OR b.P_id IS NULL
        OR c.P_id IS NULL
        OR d.P_id IS NULL
        )

只有当你有一个已知的、有限的嵌套深度时,这种方法才会起作用。根据您的需求,您应该将关系表视为一个表。你需要提升,直到你找到一条没有父母的路

这本质上是一个递归操作,因此您的SQL版本将在这里发挥作用

给定一个值,您可以找到父项或缺少,然后需要重新运行相同的测试以确定相同的内容。。。。一直到你找不到父母为止

您的情况是否限制嵌套层的数量?如果是这样的话,这可以在没有递归的情况下完成

更多讨论请参见我的问题:

编辑: 假设你有一个有限的嵌套深度3,你可以简单地重复加入以耗尽你的嵌套深度

SELECT 
    *
FROM 
    table a
LEFT OUTER JOIN table b 
    ON b.C_id = a.P_id
LEFT OUTER JOIN table c 
    ON c.C_id = b.P_id
LEFT OUTER JOIN table d 
    ON d.C_id = c.P_id
WHERE
    a.C_id = @pYourValue
    AND (
        a.P_id IS NULL 
        OR b.P_id IS NULL
        OR c.P_id IS NULL
        OR d.P_id IS NULL
        )


只有当你有一个已知的、有限的嵌套深度时,这种方法才会起作用。

为什么3是一个2岁的孩子的答案?@tom-这似乎不像我们通常认为的那样是父子关系-我认为CID 1和PID 1是不同的实体。啊,我现在明白了。谢谢JNK。为什么3是2岁孩子的答案?@tom-这似乎不像我们通常认为的那样是父母/孩子关系-我认为CID 1和PID 1是不同的实体。啊,我现在明白了。谢谢JNK。你好JNK,谢谢你的回复,但问题是C_ID和P_ID没有关系。它们是两组不同的数字。也许我应该用字母来标记C_id,而不是numbers@robert-如果是这样,那么您如何知道孩子是否也是父母?它不在你的数据模型中。@Robert-更具体地说,你是如何得到2和3的答案的?@JNK嗯,我知道每个父母的所有孩子。因此,每个父对象都是一个包含子对象的容器。因此,通过比较一个家长的所有孩子和另一个家长的所有孩子,我需要回答一个问题,如果一个家长是另一个家长的子集,基于他们的children@robert-所以这是基于一位家长是否将另一位家长的所有孩子都作为自己的孩子?你好,JNK,谢谢你的回复,但问题是C_ID和P_ID没有关系。它们是两组不同的数字。也许我应该用字母来标记C_id,而不是numbers@robert-如果是这样,那么您如何知道孩子是否也是父母?它不在你的数据模型中。@Robert-更具体地说,你是如何得到2和3的答案的?@JNK嗯,我知道每个父母的所有孩子。因此,每个父对象都是一个包含子对象的容器。因此,通过比较一个家长的所有孩子和另一个家长的所有孩子,我需要回答一个问题,如果一个家长是另一个家长的子集,基于他们的children@robert-所以这是基于父母一方是否将另一方的所有孩子都当作自己的孩子?@Matthew谢谢你的提示。它确实与DAG有关。但是,嵌套层的数量是有限的。您提到,可以不使用递归来完成。怎么做?@robert如果嵌套深度限制为n,你可以简单地自外加入n次@Matthew谢谢你的提示。它确实与DAG有关。但是,嵌套层的数量是有限的。你提到的那是可以的
没有递归就完成的。怎么做?@robert如果嵌套深度限制为n,您可以简单地自外加入n次