Я застрял с запросом 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 |
--------------------------
Нет, это не так. Когда я пытаюсь добавить это, он возвращает то же значение, что и столбец счетчика.
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 Он возвращает тот же результат, когда я удаляю sum()
, чтобы сформировать родительский запрос.
@philipxy Я просмотрел Google, но не нашел решения этой конкретной проблемы. И я считаю, что все здесь больше специалисты в своей области, чем гугл. Вот почему я пришел сюда и установил награду и уменьшил мои очки. Я знаю, "как спросить". Если у вас есть конкретный ответ, укажите его. Я думаю, что это лучший способ помочь, вместо того чтобы оставлять комментарии, которые упускают из виду главное.
Я разместил его в комментариях, чтобы рассказать вам об исследованиях, а не только для того, чтобы получить ответ на этот вопрос. Прочтите справку по поиску в гугле. Google с «site: stackoverflow.com», тегами и множеством вариантов. Хотя и без того, потому что есть много других источников для таких очевидных запросов новичка. (Re DB также ищут на сайте: dba.stackexchange.com). Средство поиска SE оставляет желать лучшего. Иногда просто не стоит искать дубликаты, которых у меня еще нет. Также я не могу проголосовать за то, чтобы закрыть это как дубликат, пока у него есть бонус.
PS Пожалуйста, в вопросах по коду указывайте минимальный воспроизводимый пример - код вырезания и вставки и исполняемый код; пример ввода с желаемым и фактическим выводом (включая дословные сообщения об ошибках); теги и четкая спецификация и объяснение. Это включает в себя наименьший код, который вы можете дать, то есть код, который, как вы показываете, в порядке, расширенный кодом, который вы показываете, не в порядке. (Основы отладки.)
Добавьте предложение 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;
Приведенный выше запрос даст мне результат, аналогичный подсчету.
Вам нужен подзапрос:
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 ;
я не думаю, что вы должны жестко кодировать типы пользователей? как он может иметь несколько динамических типов пользователей
@mayur ты проверил мой запрос?
@JuanCarlosOropeza Да, я проверил. Хорошая попытка. Из этого запроса я тоже получил сумму, но это неудобный способ сделать это. Потому что он запрашивает каждый раз для каждой строки.
Я даю другую версию. Но больше вы ничего не можете сделать. Вы пытаетесь подсчитать две разные вещи, поэтому вам нужно объединить два разных запроса.
@Mayur, я не уверен, что он будет запрашивать «сумму» каждый раз для каждой строки, движок должен быть достаточно умен, чтобы понимать, что в первом случае его нужно запустить только один раз ... и он запустит его только один раз, чтобы создать таблицу c
перед JOIN во втором случае
Первый подзапрос (подзапрос) не является «коррелированным», и MySQL выполнит его только один раз.
@JuanCarlosOropeza Я проверил оба типа и получил нужный результат. Хотя это не подходящий способ сделать это. Но я думаю, что достаточно усилий, которые вы, ребята, приложили для меня. Спасибо.
что ты имеешь в виду не апропиирован?
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 в конце, вы не получите всю сумму
точно @JuanCarlosOropeza
о да. Совершенно верно. Неправильно понял исходный вопрос. Отредактировано.
У меня возникло бы искушение спросить; Вы уверены, что вам это нужно на уровне БД?
Если вы не работаете исключительно на уровне базы данных, любая обработка этих результатов будет встроена в уровень приложения и, по-видимому, потребует некоторой формы циклического просмотра результатов.
Это может быть проще, проще и читабельнее для запуска
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
В 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
Вы можете просто объединить 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;
Выход:
+------------+------+-------+
| 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, но вы можете легко перейти на подзапрос.
Вместо
) u;
заменить) u GROUP BY u.user_type, u.count
полезно?