сумма количества (*) для всех строк в MySQL - PullRequest
2 голосов
/ 12 июня 2019

Я застрял с запросом sum(), где я хочу получить сумму count(*) значений во всех строках с group by.

Вот запрос:

select
    u.user_type as user,
    u.count,
    sum(u.count)
FROM
(
select 
    DISTINCT
    user_type,
    count(*) as count
FROM
    users
where
    (user_type = "driver" OR user_type = "passenger")
GROUP BY
    user_type
) u;

Токовый выход:

----------------------------------
|  user     |  count     |  sum  |
----------------------------------
| driver    | 58         |  90   |
----------------------------------

Ожидаемый результат:

----------------------------------
|  user     |  count     |  sum  |
----------------------------------
| driver    | 58         |  90   |
| passenger | 32         |  90   |
----------------------------------

Если я удаляю sum(u.count) из запроса, вывод будет выглядеть так:

--------------------------
|  user     |  count     |
--------------------------
| driver    | 58         |
| passenger | 32         |
--------------------------

Ответы [ 9 ]

8 голосов
/ 12 июня 2019

Вам нужен подзапрос:

   SELECT user_type, 
          Count(*) AS count,
          (SELECT COUNT(*) 
           FROM users 
           WHERE user_type IN ("driver","passenger" )) as sum  
   FROM   users 
   WHERE  user_type IN ("driver","passenger" ) 
   GROUP  BY user_type ; 

Обратите внимание, что вам не нужно distinct здесь.

ИЛИ

   SELECT user_type, 
          Count(*) AS count,
          c.sum
   FROM   users 
   CROSS JOIN ( 
           SELECT COUNT(*) as sum
           FROM users 
           WHERE user_type IN ("driver","passenger" )
         ) as c

   WHERE  user_type IN ("driver","passenger" ) 
   GROUP  BY user_type ; 
7 голосов
/ 21 июня 2019

Вы можете использовать WITH ROLLUP модификатор :

select coalesce(user_type, 'total') as user, count(*) as count
from users
where user_type in ('driver', 'passenger')
group by user_type with rollup

Будет возвращена та же информация, но в другом формате:

user      | count
----------|------
driver    |    32
passenger |    58
total     |    90

дб-скрипка

В MySQL 8 вы можете использовать COUNT() как оконную функцию :

select distinct
  user_type,
  count(*) over (partition by user_type) as count,
  count(*) over () as sum
from users
where user_type in ('driver', 'passenger');

Результат:

user_type | count | sum
----------|-------|----
driver    |    32 |  90
passenger |    58 |  90

дб-скрипка

или используйте CTE (общие табличные выражения) :

with cte as (
  select user_type, count(*) as count
  from users
  where user_type in ('driver', 'passenger')
  group by user_type
)
select user_type, count, (select sum(count) from cte) as sum
from cte

дб-скрипка

6 голосов
/ 21 июня 2019

Вы можете просто объединить SUM() OVER() с COUNT(*):

SELECT user_type, COUNT(*) AS cnt, SUM(COUNT(*)) OVER() AS total
FROM  users WHERE user_type IN ('driver', 'passenger') GROUP BY user_type;

db <> fiddle demo


Выход:

+------------+------+-------+
| user_type  | cnt  | total |
+------------+------+-------+
| passenger  |  58  |    90 |
| driver     |  32  |    90 |
+------------+------+-------+
6 голосов
/ 12 июня 2019

Попробуй это. Встроенное представление получает общую сумму:

SELECT a.user_type, 
       count(*) AS count,
       b.sum  
FROM   users a
JOIN (SELECT COUNT(*) as sum 
      FROM users 
      WHERE user_type IN ("driver","passenger" )
     ) b ON TRUE
WHERE  a.user_type IN ("driver","passenger" ) 
GROUP  BY a.user_type;
5 голосов
/ 21 июня 2019

Я хотел бы спросить; Вы уверены, что это нужно на уровне БД?

Если вы не работаете исключительно на уровне базы данных, любая обработка этих результатов будет встроена в прикладной уровень и, вероятно, потребует некоторой формы циклического просмотра результатов

Это может быть проще, проще и более читабельно для запуска

  SELECT user_type,
         COUNT(*) AS count
    FROM users
   WHERE user_type IN ("driver", "passenger")
GROUP BY user_type

.. и просто сложите общее количество на прикладном уровне

Как указал Хуан в другом ответе, DISTINCT является избыточным, поскольку GROUP BY гарантирует, что каждая результирующая строка отличается

Как и Хуан, я также предпочитаю здесь IN, а не условие OR, для user_type, поскольку я считаю его более читабельным. Это также снижает вероятность путаницы, если объединить дальнейшие условия И в будущем

Кроме того, я бы рассмотрел перемещение имен типов пользователей, "водителя" и "пассажира" в отдельную таблицу user_types и ссылки на них по столбцу идентификатора из таблицы ваших пользователей

NB Если вам абсолютно необходимо это на уровне БД, я бы рекомендовал использовать один из превосходных вариантов Пола или подход CROSS JOIN, предложенный Томом Маком и Хуаном в качестве второго предложенного решения

2 голосов
/ 12 июня 2019

В конце добавить group by предложение для user-type, например:

select
    u.user_type as user,
    u.count,
    sum(u.count)
FROM
(
select 
    DISTINCT
    user_type,
    count(*) as count
FROM
    users
where
    (user_type = "driver" OR user_type = "passenger")
GROUP BY
    user_type
) u GROUP BY u.user_type;
1 голос
/ 26 июня 2019

Tom Mac Правильно объясните Ваш ответ.Вот еще один способ сделать это.Я проверяю производительность запроса и не обнаружил никакой разницы в пределах 1000 записей

   select user_type,Countuser,(SELECT COUNT(*) 
   FROM users 
   WHERE user_type IN ('driver','passenger ') )as sum from (
   select user_type,count(*) as Countuser from users a
   where a.user_type='driver'
   group by a.user_type
   union
   select user_type,count(*) as Countuser from users b
   where b.user_type='passenger'
   group by b.user_type
   )c
   group by user_type,Countuser
0 голосов
/ 28 июня 2019

Попробуйте это:

WITH SUB_Q AS (
  SELECT USER_TYPE, COUNT (*) AS CNT
  FROM USERS
  WHERE USER_TYPE = "passenger" OR USER_TYPE = "driver"
  GROUP BY USER_TYPE
), 
SUB_Q2 AS (
  SELECT SUM(CNT) AS SUM_OF_COUNT
  FROM SUB_Q
)
SELECT A.USER_TYPE, A.CNT AS COUNT, SUB_Q2 AS SUM
FROM SUB_Q JOIN SUB_Q2 ON (TRUE);

Я использовал диалект postgresql, но вы можете легко перейти к подзапросу.

0 голосов
/ 12 июня 2019
select
    u.user_type as user,
    u.count,
    sum(u.count)
FROM users group by user
...