选择自引用表中未被任何其他行指向的行。

4

我有一张自引用表,我在寻找没有其他行指向它的行方面遇到了麻烦 - 或者说,换句话说,获取那些不是其他任何行的父级的行,当然,这意味着它们没有子节点。

这是我的带有示例数据的表:

+----+------+--------+
| id | name | cat_id |
+----+------+--------+
|  1 | C1   |        |
|  2 | C2   |        |
|  3 | C3   |      1 |
|  4 | C4   |      2 |
|  5 | C5   |      2 |
|  6 | C6   |      5 |
+----+------+--------+

在这里,cat_id 是父级。这是一种“表示”: . ├── C1 | └── C3 └── C2 ├── C4 └── C5 └── C6 如上所述,类别可以无限地拥有子类别,并且它们由指向cat_id来定义。如果它是一个“主”类别,它就不指向任何东西。我可以通过在cat_id中选择NULL来获取所有没有“父级”的类别,但是如何选择没有“子级”的类别?
我尝试过:
SELECT
    c1.id, c1.name, c1.cat_id
FROM
    cat c1
INNER JOIN
    cat c2
ON
    c1.id != c2.cat_id

但是这不仅会返回重复的行,而且还包括有子类别的类别。预期结果在表示中用粗体标出。您可以在this SQLFiddle中运行测试。
我该如何实现这一点?是否可以在不使用递归的情况下实现?

我添加了标签以使问题更具体,但我认为这基本上是一个与SQL相关的问题。 - FirstOne
可能是重复的问题,与https://stackoverflow.com/questions/23751672/sql-query-how-to-extract-last-child-of-a-table相似。 - William Perron
这种类型的关系通常使用递归进行评估。您试图避免递归的特定原因吗? - user681574
3个回答

2

寻找没有子节点的方法之一是使用 not exists,它只选择在 cat_id 列中没有被引用为父级的行:

select id from cat c1
where not exists (
    select 1 from cat c2 where c2.cat_id = c1.id
)

2
这可能是您最初查询的目标:
select a.*
from cat a left outer join
   cat b on a.id = b.cat_id
where b.cat_id is null

1
好的,我明白了...从表格(left)中获取所有内容 -> 带有父级的内容进行合并(join/on),没有子级的内容不会合并,因此它们将没有引用 -> 移除空引用(where)...非常感谢。 - FirstOne

1

试试这个:

select * from cat
where id not in (
    select distinct cat_id 
    from cat
    where cat_id is not null)

查找没有其他行指向它的行,意味着查找 'cat_id' 列中没有任何一行包含 'id' 的行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接