比当前的更清洁 SQL CTE

Cleaner SQL CTE than the current one

目前我使用以下 CTE 来抓取一个类别和它下面的任何类别:

WITH RECURSIVE tree AS (
SELECT * FROM (
    SELECT categoryId, 
          categoryName, 
          categoryParentId,
          categoryDescr,
          categoryType,
          categoryDC,
          categoryLedgerId,
          1 as categoryDepth
    FROM tbl_categories
    WHERE categoryId = '.$categoryId.'
    UNION
    SELECT categoryId, 
          categoryName, 
          categoryParentId,
          categoryDescr,
          categoryType,
          categoryDC,
          categoryLedgerId,
          1 as categoryDepth
    FROM tbl_categories_custom
    WHERE categoryId = '.$categoryId.'
) AS combined

UNION ALL

SELECT p.categoryId,
        p.categoryName,
        p.categoryParentId,
        p.categoryDescr,
        p.categoryType,
        p.categoryDC,
        p.categoryLedgerId, 
        t.categoryDepth + 1
        FROM (
           SELECT * FROM tbl_categories
           UNION
           SELECT * FROM tbl_categories_custom
        ) AS p
        JOIN tree t ON t.categoryId = p.categoryParentId
)
SELECT *
FROM tree

然而,正如@trincot 在 中向我展示的那样,它可以做得更干净。

他那边的版本抓住了一个类别和它上面的任何类别。

这个应该反着做;抓住任何类别和它下面的任何类别。它是做什么的。但是现在我读了他的另一个版本似乎太复杂了。

如何简化这个 CTE?

事实上,您可以通过首先为联合创建一个通用 table 表达式,然后再执行递归表达式来缩短这个时间。

该查询与另一个问题中发布的查询非常相似。主要变化是 inner join ... on 子句中的连接条件现在颠倒了。 = 1 部分是您与 PHP 变量进行比较的地方:

with recursive 
base as (
    select * from tbl_categories
    union
    select * from tbl_categories_custom
),
cte as (
    select 1 as categoryDepth,
           base.* 
    from   base
    where  categoryId = 1
    union
    select cte.categoryDepth + 1, 
           base.*
    from   cte
    inner join base
            on cte.categoryId = base.categoryParentId
)
select   *
from     cte;