WHERE 子句在 CTE 之后找不到列?

WHERE clause does not find column after a CTE?

SQL 中的 CTE 和子查询的新功能。
我有 3 个表:

categories (category_code, category)
countries (country_code, country, continent)
businesses (business, year_founded, category_code, country_code)

目标是了解世界上最古老的企业。我使用了 CTE:

WITH bus_cat_cont AS (
    SELECT business, year_founded, category, country,   
           continent
    FROM businesses AS b
    INNER JOIN categories AS c1
    ON b.category_code = c1.category_code
    INNER JOIN countries AS c2
    ON b.country_code = c2.country_code
    )
SELECT continent,
       category,
       COUNT(business) AS n
FROM bus_cat_cont
WHERE n > 5
GROUP BY continent, category
ORDER BY n DESC;

代码在没有 WHERE n > 5 的情况下也能正常工作。但是添加之后,我得到了错误:

column "n" does not exist

我意识到有一种更简单的方法可以在没有 CTE 的情况下获得我想要的输出。
但我想知道:为什么会出现此错误?

这可行:

WITH bus_cat_cont AS (
   SELECT business, year_founded, category, country, continent
   FROM   businesses AS b
   JOIN   categories AS c1 ON b.category_code = c1.category_code
   JOIN   countries  AS c2 ON b.country_code = c2.country_code
   )
SELECT continent, category, count(business) AS n
FROM   bus_cat_cont
-- WHERE  n > 5                -- wrong
GROUP  BY continent, category
HAVING count(business) > 5     -- right
ORDER  BY n DESC;

output 列名称“n”在 WHEREHAVING 子句中(尚)不可见。考虑 SQL 查询中的事件序列:

  • Best way to get result count before LIMIT was applied

郑重声明,该结果与您宣布的 “看看世界上最古老的企业” 的目标没有明显联系。 year_founded 未在查询中使用。
您获得了企业中最常见的 continent/category 组合。

除此之外,可能更好:

SELECT co.continent, ca.category, n
FROM  (
   SELECT category_code, country_code, count(*) AS n
   FROM   businesses
   GROUP  BY 1, 2
   HAVING count(*) > 5
   ) b
JOIN   categories ca USING (category_code)
JOIN   countries  co USING (country_code)
ORDER  BY n DESC;

真的不需要CTE。

先聚合,后加入。参见:

  • Query with LEFT JOIN not returning rows for count of 0

除了更快,这也更安全。虽然 category_codecountry_code 应该定义为 UNIQUE,但 continentcategory 可能并非如此。 (您可能需要额外输出代码以消除歧义。)

count(*) is implemented 单独且稍快 - 等效于 business 定义为 NOT NULL.