Сумма count(*) для всех строк в MySQL

Я застрял с запросом 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         |
--------------------------

Вместо ) u; заменить ) u GROUP BY u.user_type, u.count полезно?

Arulkumar 12.06.2019 10:22

Нет, это не так. Когда я пытаюсь добавить это, он возвращает то же значение, что и столбец счетчика.

Mayur 12.06.2019 10:24
SELECT DISTINCT(user_type) as diff, COUNT(user_type) total from users where (user_type = "driver" OR user_type = "passenger") group by user_type должно работать.
bencagri 12.06.2019 10:27

@bencagri Он возвращает тот же результат, когда я удаляю sum(), чтобы сформировать родительский запрос.

Mayur 12.06.2019 10:29

@philipxy Я просмотрел Google, но не нашел решения этой конкретной проблемы. И я считаю, что все здесь больше специалисты в своей области, чем гугл. Вот почему я пришел сюда и установил награду и уменьшил мои очки. Я знаю, "как спросить". Если у вас есть конкретный ответ, укажите его. Я думаю, что это лучший способ помочь, вместо того чтобы оставлять комментарии, которые упускают из виду главное.

Mayur 21.06.2019 10:47

Я разместил его в комментариях, чтобы рассказать вам об исследованиях, а не только для того, чтобы получить ответ на этот вопрос. Прочтите справку по поиску в гугле. Google с «site: stackoverflow.com», тегами и множеством вариантов. Хотя и без того, потому что есть много других источников для таких очевидных запросов новичка. (Re DB также ищут на сайте: dba.stackexchange.com). Средство поиска SE оставляет желать лучшего. Иногда просто не стоит искать дубликаты, которых у меня еще нет. Также я не могу проголосовать за то, чтобы закрыть это как дубликат, пока у него есть бонус.

philipxy 21.06.2019 11:18

PS Пожалуйста, в вопросах по коду указывайте минимальный воспроизводимый пример - код вырезания и вставки и исполняемый код; пример ввода с желаемым и фактическим выводом (включая дословные сообщения об ошибках); теги и четкая спецификация и объяснение. Это включает в себя наименьший код, который вы можете дать, то есть код, который, как вы показываете, в порядке, расширенный кодом, который вы показываете, не в порядке. (Основы отладки.)

philipxy 21.06.2019 11:19
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
1
7
4 320
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

Добавьте предложение 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;

Приведенный выше запрос даст мне результат, аналогичный подсчету.

Mayur 12.06.2019 10:40
Ответ принят как подходящий

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

   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 ; 

я не думаю, что вы должны жестко кодировать типы пользователей? как он может иметь несколько динамических типов пользователей

Mustahsan 12.06.2019 10:24

@mayur ты проверил мой запрос?

Juan Carlos Oropeza 12.06.2019 10:53

@JuanCarlosOropeza Да, я проверил. Хорошая попытка. Из этого запроса я тоже получил сумму, но это неудобный способ сделать это. Потому что он запрашивает каждый раз для каждой строки.

Mayur 12.06.2019 11:54

Я даю другую версию. Но больше вы ничего не можете сделать. Вы пытаетесь подсчитать две разные вещи, поэтому вам нужно объединить два разных запроса.

Juan Carlos Oropeza 12.06.2019 18:43

@Mayur, я не уверен, что он будет запрашивать «сумму» каждый раз для каждой строки, движок должен быть достаточно умен, чтобы понимать, что в первом случае его нужно запустить только один раз ... и он запустит его только один раз, чтобы создать таблицу c перед JOIN во втором случае

Arth 21.06.2019 15:17

Первый подзапрос (подзапрос) не является «коррелированным», и MySQL выполнит его только один раз.

Paul Spiegel 21.06.2019 18:02

@JuanCarlosOropeza Я проверил оба типа и получил нужный результат. Хотя это не подходящий способ сделать это. Но я думаю, что достаточно усилий, которые вы, ребята, приложили для меня. Спасибо.

Mayur 24.06.2019 09:02

что ты имеешь в виду не апропиирован?

Juan Carlos Oropeza 24.06.2019 14:27
select
    u.user_type as user,
    u.count,
    sum(u.count)
FROM users group by user

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

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;

если вы сделаете group by в конце, вы не получите всю сумму

Juan Carlos Oropeza 12.06.2019 10:26

точно @JuanCarlosOropeza

Mayur 12.06.2019 10:30

о да. Совершенно верно. Неправильно понял исходный вопрос. Отредактировано.

Tom Mac 12.06.2019 11:08

У меня возникло бы искушение спросить; Вы уверены, что вам это нужно на уровне БД?

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

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

  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 и ссылки на них по столбцу идентификаторов из вашей таблицы пользователей.

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

Вы можете использовать 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

db-рабочий пример

В 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

db-рабочий пример

или используйте 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

db-рабочий пример

Вы можете просто объединить 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<>демонстрация скрипки


Выход:

+------------+------+-------+
| user_type  | cnt  | total |
+------------+------+-------+
| passenger  |  58  |    90 |
| driver     |  32  |    90 |
+------------+------+-------+

Том Мак Объясните правильно свой ответ. Вот еще один способ сделать это. Я проверяю производительность запроса и не нашел никакой разницы в пределах 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

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

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, но вы можете легко перейти на подзапрос.

Другие вопросы по теме