我有一个SQL SELECT查询,也使用GROUP BY,
我想统计GROUP BY子句过滤结果集后的所有记录。
有什么方法可以直接用SQL做到这一点吗?例如,如果我有用户表,想要选择不同的城镇和用户总数:
SELECT `town`, COUNT(*)
FROM `user`
GROUP BY `town`;
我想有一个列的所有城镇和另一个与用户的数量在所有行。
一个有3个镇和58个用户的结果的例子是:
Town |
Count |
Copenhagen |
58 |
New York |
58 |
Athens |
58 |
10个未删除的答案;大多数不做用户要求的事情。大多数回答错误地理解了这个问题,认为每个城镇有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)
显示会话状态,例如'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是否为非空,这在此上下文中是不必要的。
这将做你想做的(城镇列表,每个城镇的用户数量):
SELECT `town`, COUNT(`town`)
FROM `user`
GROUP BY `town`;
在使用GROUP BY语句时,可以使用大多数聚合函数
(COUNT, MAX, COUNT DISTINCT等)
更新:
你可以为用户数量声明一个变量并保存结果,然后选择变量的值:
DECLARE @numOfUsers INT
SET @numOfUsers = SELECT COUNT(*) FROM `user`;
SELECT DISTINCT `town`, @numOfUsers FROM `user`;
10个未删除的答案;大多数不做用户要求的事情。大多数回答错误地理解了这个问题,认为每个城镇有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)
显示会话状态,例如'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是否为非空,这在此上下文中是不必要的。