SQL聚合函数别名

Pau*_*enn 5 sql postgresql case aggregate-functions having

我是SQL的初学者,这是我被要求解决的问题:

说一个大城市被定义为一个place类型的city具有至少10万人口.编写一个返回(state_name,no_big_city,big_city_population)订购方案的SQL查询state_name,列出那些拥有(a)至少五个大城市或(b)至少一百万人居住在大城市的州.列state_namenamestate,no_big_city是在国家大城市的数量,并且big_city_population为生活在该州大城市的人数.

现在,据我所知,以下查询返回正确的结果:

SELECT state.name AS state_name
     , COUNT(CASE WHEN place.type = 'city' AND place.population >= 100000 THEN 1 ELSE NULL END) AS no_big_city
     , SUM(CASE WHEN place.type = 'city' AND place.population >= 100000 THEN place.population ELSE NULL END) AS big_city_population
FROM state
JOIN place
ON state.code = place.state_code
GROUP BY state_name
    HAVING
        COUNT(CASE WHEN place.type = 'city' AND place.population >= 100000 THEN 1 ELSE NULL END) >= 5 OR
        SUM(CASE WHEN place.type = 'city' AND place.population >= 100000 THEN place.population ELSE NULL END) >= 1000000
ORDER BY state_name;
Run Code Online (Sandbox Code Playgroud)

但是,代码中使用的两个聚合函数出现两次.我的问题:有没有办法让这个代码重复消失保留功能?

要清楚,我已经尝试使用别名,但我只是得到一个"列不存在"错误.

Erw*_*ter 5

该手册阐明:

输出列的名称可用于在ORDER BYand GROUP BY子句中引用该列的值,但不能在WHEREor HAVING子句中引用 ; 在那里,您必须写出表达式。

大胆强调我的。

您可以避免使用子查询或CTE重复输入长表达式:

SELECT state_name, no_big_city, big_city_population
FROM  (
   SELECT s.name AS state_name
        , COUNT(*)        FILTER (WHERE p.type = 'city' AND p.population >= 100000) AS no_big_city
        , SUM(population) FILTER (WHERE p.type = 'city' AND p.population >= 100000) AS big_city_population
   FROM   state s
   JOIN   place p ON s.code = p.state_code
   GROUP  BY s.name -- can be input column name as well, best schema-qualified to avoid ambiguity
   ) sub
WHERE  no_big_city >= 5
   OR  big_city_population >= 1000000
ORDER  BY state_name;
Run Code Online (Sandbox Code Playgroud)

在此过程中,我简化了聚合FILTER子句(Postgres 9.4+):

但是,我建议从以下开始更简单,更快速的查询:

SELECT s.state_name, p.no_big_city, p.big_city_population
FROM   state s
JOIN  (
   SELECT state_code      AS code  -- alias just to simplify join
        , count(*)        AS no_big_city
        , sum(population) AS big_city_population
   FROM   place
   WHERE  type = 'city'
   AND    population >= 100000
   GROUP  BY 1  -- can be ordinal number referencing position in SELECT list
   HAVING count(*) >= 5 OR sum(population) >= 1000000  -- simple expressions now
   ) p USING (code)
ORDER  BY 1;    -- can also be ordinal number
Run Code Online (Sandbox Code Playgroud)

我正在演示引用GROUP BY和中的表达式的另一种选择ORDER BY。仅在不影响可读性和可维护性的情况下使用它。