如何在同一个 select 语句中使用 count 和 group by

新手上路,请多包涵

我有一个 SQL SELECT 查询也使用 GROUP BY ,我想计算 GROUP BY 子句过滤结果集后的所有记录。

有什么办法可以直接用 SQL 做到这一点?例如,如果我有表 users 并想选择不同的城镇和用户 总数

 SELECT `town`, COUNT(*)
FROM `user`
GROUP BY  `town`;

我想有一列包含所有城镇,另一列包含所有行中的用户数。

共有 3 个城镇和 58 个用户的结果示例如下:

镇数数哥本哈根58纽约58雅典58

原文由 Stavros 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 635
2 个回答

这将做你想要 的(城镇列表,每个城镇的用户数量)

 SELECT `town`, COUNT(`town`)
FROM `user`
GROUP BY `town`;

使用 GROUP BY 语句时,您可以使用大多数 聚合函数COUNTMAXCOUNT DISTINCT 等)043ed。

更新: 您可以为用户数声明一个变量并将结果保存在那里,然后 SELECT 变量的值:

 DECLARE @numOfUsers INT
SET @numOfUsers = SELECT COUNT(*) FROM `user`;

SELECT DISTINCT `town`, @numOfUsers FROM `user`;

原文由 Oded 发布,翻译遵循 CC BY-SA 4.0 许可协议

十个未删除的答案;大多数人 不做 用户要求的事情。大多数答案误读了这个问题,认为 每个 城镇有 58 个用户,而不是总共 58 个用户。即使是少数正确的也不是最佳的。

 mysql> flush status;
Query OK, 0 rows affected (0.00 sec)

SELECT  province, total_cities
    FROM       ( SELECT  DISTINCT province  FROM  canada ) AS provinces
    CROSS JOIN ( SELECT  COUNT(*) total_cities  FROM  canada ) AS tot;
+---------------------------+--------------+
| province                  | total_cities |
+---------------------------+--------------+
| Alberta                   |         5484 |
| British Columbia          |         5484 |
| Manitoba                  |         5484 |
| New Brunswick             |         5484 |
| Newfoundland and Labrador |         5484 |
| Northwest Territories     |         5484 |
| Nova Scotia               |         5484 |
| Nunavut                   |         5484 |
| Ontario                   |         5484 |
| Prince Edward Island      |         5484 |
| Quebec                    |         5484 |
| Saskatchewan              |         5484 |
| Yukon                     |         5484 |
+---------------------------+--------------+
13 rows in set (0.01 sec)

SHOW session status LIKE 'Handler%';

 +----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Handler_commit             | 1     |
| Handler_delete             | 0     |
| Handler_discover           | 0     |
| Handler_external_lock      | 4     |
| Handler_mrr_init           | 0     |
| Handler_prepare            | 0     |
| Handler_read_first         | 3     |
| Handler_read_key           | 16    |
| Handler_read_last          | 1     |
| Handler_read_next          | 5484  |  -- One table scan to get COUNT(*)
| Handler_read_prev          | 0     |
| Handler_read_rnd           | 0     |
| Handler_read_rnd_next      | 15    |
| Handler_rollback           | 0     |
| Handler_savepoint          | 0     |
| Handler_savepoint_rollback | 0     |
| Handler_update             | 0     |
| Handler_write              | 14    |  -- leapfrog through index to find provinces
+----------------------------+-------+

在OP的上下文中:

 SELECT  town, total_users
    FROM       ( SELECT  DISTINCT town  FROM  canada ) AS towns
    CROSS JOIN ( SELECT  COUNT(*) total_users  FROM  canada ) AS tot;

由于 tot 中只有一行,因此 CROSS JOIN 不像其他情况下那样庞大。

通常的模式是 COUNT(*) 而不是 COUNT(town) 。后者意味着检查 town 是否不为空,这在这种情况下是不必要的。

原文由 Rick James 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进