是否可以将 LEFT JOIN 修改为 return 既有匹配又有匹配的空行?

Is it possible to modify a LEFT JOIN to return a null row where there is a match as well as the match?

我有一个代表层次结构的 table,因此它同时具有 idparent_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;

然而,这会扫描 table 三次。我试图对此进行一些优化,所以尝试了这个:

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 方法那样扫描 table 三次?

 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)
   */

Returns :

ID
3
4
5

并提供更好的性能

这也行,但执行计划变得讨厌

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