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


223

我有一个分组的SQL选择查询。我想对group by语句之后的所有记录进行计数。有没有办法直接从SQL?例如,有一个包含用户的表格,我想选择不同的城镇和用户总数

select town, count(*) from user
group by town

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

共有3个镇和58个用户的结果示例是:

Town         Count
Copenhagen   58
NewYork      58
Athens       58

您的意思是您希望您的结果集包含2个计数,一个统计城镇,一个统计用户?
Leslie

2
因此,您要为每个城镇排一行,并且在每一行中,第2列包含所有用户的总数?那么第2列的每一行都有相同的值吗?如果您编辑以包括样本数据和所需的输出,我们将能够为您提供所需的确切信息。
AakashM 2010年

你是对的AakashM!我刚刚编辑了它。
Stavros


1
给读者的警告:大多数答案都无法为查询提供更新后的答案。
瑞克·詹姆斯

Answers:


271

这将完成您想要的操作(城镇列表以及每个城镇中的用户数量):

select town, count(town) 
from user
group by town

使用时,您可以使用大多数聚合函数GROUP BY

更新(对问题和评论进行更改之后)

您可以为用户数量声明一个变量,并将其设置为用户数量,然后选择该变量。

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

SELECT DISTINCT town, @numOfUsers
FROM user

这正是OP写的吗?nvm,我看到了您的与众不同,您是在计算城镇,而不是* ....
Leslie

@Leslie-两个查询之间没有区别。他们将返回相同的结果集。我只是不喜欢使用*... OP回答了他自己的问题,但似乎没有对其进行测试,我只是在验证它是正确的:) fredosaurus.com/notes-db/select/groupby.html
Oded

再次不是我所希望的,但是这似乎是最好的解决方案..;)谢谢
Stavros

149

您可以使用COUNT(DISTINCT ...)

SELECT COUNT(DISTINCT town) 
FROM user

3
可以起到魅力的作用……应选择主要答案。
维克多

2
我认为它们的意思是如果您在WHERE子句中添加COUNT(DISTINCT镇)。那是因为它是一个聚合函数,需要在HAVING子句中提供。由于COUNT和DISTINCT关键字,由于COUNT和DISTINCT关键字,此SQL查询会误导某些人,因为SELECT COUNT(DISTINCT镇)变成了隐式GROUP BY,每个关键字本身也将隐式分组。
A. Greensmith '16

谢谢。赞成。正是需要的-组+算入一个操作并获得单行结果。
绿色,

该死..我不知道那是可能的!
Hugo S. Mendes

1
@milkovsky-不,您不必删除它。我只是感到恼火的是,这个问题与许多答案分叉起来解决了两个不同的问题。您的答案有两种不同的方式-无town列,而且COUNTs是错误的内容(城镇而不是用户)。
瑞克·詹姆斯

37

另一种方法是:

/* Number of rows in a derived table called d1. */
select count(*) from
(
  /* Number of times each town appears in user. */
  select town, count(*)
  from user
  group by town
) d1

5
需要别名,否则将无法在mysql中工作。从()agr中选择count(*)
amas

4

使用Oracle,您可以使用分析功能:

select town, count(town), sum(count(town)) over () total_count from user
group by town

您的其他选择是使用子查询:

select town, count(town), (select count(town) from user) as total_count from user
group by town

像最后一个这样的东西可以工作,但是我想看看是否还有其他解决方案
。– Stavros

而且您不能使用第一个(分析功能)选项吗?您正在使用什么数据库平台?
Tommi

@Stavros:最后一个很慢
Michael Buen 2010年

4

如果您想按计数排序(听起来很简单,但我找不到如何做到这一点的答案),可以这样做:

        SELECT town, count(town) as total FROM user
        GROUP BY town ORDER BY total DESC

4

十个未删除的答案;大多数人不会按照用户的要求进行操作。大多数答案误以为是每个城镇有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为空,这在此上下文中是不必要的。


2

您可以像milkovovsky所说的那样在COUNT内部使用DISTINCT

就我而言:

select COUNT(distinct user_id) from answers_votes where answer_id in (694,695);

这将拉取被认为与user_id相同的答案投票数


2

我知道这是SQL Server中的旧帖子:

select  isnull(town,'TOTAL') Town, count(*) cnt
from    user
group by town WITH ROLLUP

Town         cnt
Copenhagen   58
NewYork      58
Athens       58
TOTAL        174

5
回答旧帖子没有错。但是,请提供您的代码以及代码本身的说明。
Shelvacu

与MySQL相当的(IFNULL而不是ISNULL)导致每个城镇的数字不同;用户想要总数。根据问题,总数是58,而不是174。
瑞克·詹姆斯

1

如果要选择镇和用户总数,则可以在下面使用此查询:

SELECT Town, (SELECT Count(*) FROM User) `Count` FROM user GROUP BY Town;

假设(也许合理)在中没有重复的“用户” User
瑞克·詹姆斯

1

如果要使用“选择所有带计数的查询”选项,请尝试此操作...

 select a.*, (Select count(b.name) from table_name as b where Condition) as totCount from table_name  as a where where Condition

感谢您提供此代码段,它可能会提供一些有限的即时帮助。正确的解释显示为什么这是解决问题的好方法,从而大大提高其长期价值,并且对于将来有其他类似问题的读者来说,将更为有用。请编辑您的答案以添加一些解释,包括您所做的假设。
Toby Speight

0

尝试以下代码:

select ccode, count(empno) 
from company_details 
group by ccode;

我们用这个代码来查找每个现今计算,每CCODE(公司代码)例如一共有多少员工:计数(EMPNO)是1839年为CCODE 1和COUNT(EMPNO)为9421的CCODE 47
balajibran
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.