SQL 聚合函数别名

标签 sql postgresql case aggregate-functions having

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

Say that a big city is defined as a place of type city with a population of at least 100,000. Write an SQL query that returns the scheme (state_name,no_big_city,big_city_population) ordered by state_name, listing those states which have either (a) at least five big cities or (b) at least one million people living in big cities. The column state_name is the name of the state, no_big_city is the number of big cities in the state, and big_city_population is the number of people living in big cities in the state.

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

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;

但是,代码中使用的两个聚合函数出现了两次。我的问题:是否有任何方法可以使此代码重复消失并保留功能?

明确地说,我已经尝试过使用别名,但我只是收到“列不存在”错误。

最佳答案

The manual clarifies:

An output column's name can be used to refer to the column's value in ORDER BY and GROUP BY clauses, but not in the WHERE or HAVING clauses; there you must write out the expression instead.

大胆强调我的。

您可以避免使用子查询或 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;

同时,我使用聚合 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

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

关于SQL 聚合函数别名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40536933/

相关文章:

java - 如果子查询的结果集列值为 NULL,则显示某个值

android - 单击时更改 MenuItem 可见性

mysql - 从一个表中选择多列并作为行插入到另一个表中

php - 二维数组的使用

SQL:根据另一列将一列求和为多列

python - 如何使用 ponyorm 中的实体进行 get() 查询

sql - 如何在 SQL 中获取 "top X with the rest"?

sql - 插入 2 列主键

sql - ROLLBACK TRANSACTION 请求没有对应的 BEGIN TRANSACTION

MySQL : can CASE - vary its query between Insert or Select?