Как использовать count и group by в одном операторе выбора - PullRequest
204 голосов
/ 27 апреля 2010

У меня есть запрос выбора SQL, который имеет группу по. Я хочу посчитать все записи после группировки по заявлению. Есть ли способ для этого прямо из SQL? Например, имея таблицу с пользователями, я хочу выбрать разные города и общее количество пользователей

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

Я хочу иметь столбец со всеми городами, а другой - количество пользователей во всех строках.

Пример результата для 3 городов и 58 пользователей:

Town         Count
Copenhagen   58
NewYork      58
Athens       58

Ответы [ 11 ]

260 голосов
/ 27 апреля 2010

Это будет делать то, что вы хотите (список городов, с количеством пользователей в каждом):

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
137 голосов
/ 11 июня 2014

Вы можете использовать COUNT(DISTINCT ...):

SELECT COUNT(DISTINCT town) 
FROM user
31 голосов
/ 15 октября 2013

Другой способ:

/* 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
4 голосов
/ 18 декабря 2013

Если вы хотите заказать по количеству (звучит просто, но я не могу найти ответ в стеке о том, как это сделать), вы можете сделать:

        SELECT town, count(town) as total FROM user
        GROUP BY town ORDER BY total DESC
3 голосов
/ 28 апреля 2010

С 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
2 голосов
/ 12 марта 2016

Я знаю, что это старый пост в 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
2 голосов
/ 06 октября 2014

Вы можете использовать DISTINCT внутри COUNT, как сказал Милковский

в моем случае:

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

Это приведет к подсчету голосов за один и тот же user_id, равному одному счету

1 голос
/ 07 июля 2018

Десять не удаленных ответов; большинство делают , а не делают то, что просил пользователь. Большинство Ответов неверно истолковывают вопрос, считая, что в каждом городе 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  
+----------------------------+-------+

В контексте ОП:

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 на ненулевое значение, что в этом контексте не требуется.

1 голос
/ 14 октября 2014

Если вы хотите выбрать город и общее количество пользователей, вы можете использовать этот запрос ниже:

SELECT Town, (SELECT Count(*) FROM User) `Count` FROM user GROUP BY Town;
0 голосов
/ 05 декабря 2017

, если вы хотите использовать опцию Select All Query With Count, попробуйте это ...

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