【问题标题】:Group By Count from Multiple Tables with conditions根据条件从多个表中按计数分组
【发布时间】:2020-12-24 17:59:03
【问题描述】:

我有 3 个不同的表,国家、城市和客户。表格如下:

国家表:

id   country_name
1    UK
2    US
3   Brazil
:    
n   Canada

城市表

id  city_name  postal_code  country_id
1    London        30090         1
2    Dallas        20909         2
3    Rio           29090         3
4    Atlanta       30318         2
:
n    Vancouver     32230         n

客户表

id    customer_name     city_id
1        John             1
2        Pete             3
3        Dave             2
4        May              2
5        Chuck            4
6        Sam              3
7        Henry            3

***country.id 是引用 city.country_id,city.id 是引用 customer.city_id

我想写一个查询,可以提取关联城市的国家名称、城市名称和客户数量。但是在一个条件下,查询将返回所有城市的客户数超过所有城市的平均客户数

如下所示,这是正确的输出

UK London 2
Brazil Rio 3

但我一直得到这个输出,这是不正确的

UK London 2
US Dallas 2
US Atlanta 1
Brazil Rio 3

我写了一个 SQL 查询,但它没有给我想要的结果

SELECT country.country_name, city.city_name, COUNT(customer.city_id) from country 
JOIN city on country.id = city.country_id 
JOIN customer on city.id = customer.city_id
Group by city_name,country.country_name;

我想知道如何执行此操作并修复我的代码?

【问题讨论】:

    标签: sql join group-by subquery


    【解决方案1】:

    你可以使用窗口函数:

    SELECT cc.*
    FROM (SELECT co.country_name, ci.city_name, COUNT(*) AS cnt,
                 AVG(COUNT(*)) OVER () as avg_count
          FROM country co JOIn
               city ci
               ON co.id = ci.country_id JOIN 
               customer cu
               ON ci.id = cu.city_id
          GROUP BY ci.city_name, co.country_name
         ) cc
    WHERE cnt > avg_count;
    

    【讨论】:

      【解决方案2】:

      您需要将查询嵌套到子查询中,以便获取计数的平均值并将当前计数与它进行比较。如果您使用的是支持 CTE 的 SQL,则可以使用一个,例如

      WITH cnts AS (
        SELECT country.country_name, city.city_name, COUNT(customer.city_id) AS cnt 
        FROM country 
        JOIN city on country.id = city.country_id 
        JOIN customer on city.id = customer.city_id
        GROUP BY city_name,country.country_name
      )
      SELECT *
      FROM cnts
      WHERE cnt > (SELECT AVG(cnt) FROM cnts)
      

      否则查询会变得更加复杂,主查询也需要作为WHERE 子句中的子查询:

      SELECT country.country_name, city.city_name, COUNT(customer.city_id) AS cnt 
      FROM country 
      JOIN city on country.id = city.country_id 
      JOIN customer on city.id = customer.city_id
      GROUP BY city_name,country.country_name
      HAVING COUNT(customer.city_id) > (SELECT AVG(cnt) FROM (
        SELECT country.country_name, city.city_name, COUNT(customer.city_id) AS cnt 
        FROM country 
        JOIN city on country.id = city.country_id 
        JOIN customer on city.id = customer.city_id
        GROUP BY city_name,country.country_name
      ) cnts2)
      

      在这两种情况下,样本数据的输出都是:

      country_name    city_name   cnt
      Brazil          Rio         3
      US              Dallas      2
      

      Demo on dbfiddle

      【讨论】:

        猜你喜欢
        • 2019-02-11
        • 1970-01-01
        • 2021-05-13
        • 2018-05-18
        • 1970-01-01
        • 2020-09-24
        • 1970-01-01
        • 2020-01-07
        • 2021-08-01
        相关资源
        最近更新 更多