我有一个代表层次结构的表,因此它同时包含id
和parent_id
。此层次结构只有两个级别,父级在parent_id
中为空。我试图获取父级具有特定属性的层次结构中每个项目的记录。例如,使用此数据:
CREATE TABLE t (id int, parent_id int, property bit);
INSERT INTO t VALUES
(1, null, 0),
(2, 1, null),
(3, null, 1),
(4, 3, null),
(5, null, 1);
我想要检索:
======
| ID |
======
| 3 |
| 4 |
| 5 |
======
我可以使用UNION
这样做:
SELECT
id
FROM
t
WHERE
property = 1 AND parent_id is null
UNION
SELECT
child.id
FROM
t parent
INNER JOIN t child
ON parent.id = child.parent_id
WHERE
parent.property = 1
ORDER BY
id;
然而,这会扫描桌子三次。我试图优化这一点,所以尝试了这个:
SELECT
ISNULL(child.id, parent.id)
FROM
t parent
LEFT JOIN t child
ON parent.id = child.parent_id
WHERE
parent.property = 1
然而,这只是给了我:
======
| ID |
======
| 4 |
| 5 |
======
第3行未返回,因为LEFT JOIN
没有为3提供单独的行,因为它与第4行中的parent_id
匹配。有没有办法修改LEFT JOIN
以提供我需要的额外行?是否有其他方法可以执行此查询,而不涉及UNION
方法扫描表三次?
答案 0 :(得分:2)
SELECT
ISNULL(child.id, parent.id)
FROM
t child
LEFT JOIN t parent
ON child.parent_id = parent.id
WHERE
parent.property = 1 OR child.property = 1
/* you might want to do this instead to be sure to include only the parent nodes
with the property set to 1 :
parent.property = 1 OR (child.property = 1 AND parent.id IS NULL)
*/
返回:
ID
3
4
5
并提供更好的表现
答案 1 :(得分:0)
这也有效,但执行计划变得讨厌
WITH n(id, parent_id) AS
(SELECT id, parent_id
FROM t
WHERE property = 1
UNION ALL
SELECT nplus1.id, nplus1.parent_id
FROM t as nplus1
inner join n on n.id = nplus1.parent_id)
SELECT id FROM n
order by id