#mysql #group-by #count #left-join #union
Вопрос:
Я потратил больше времени на написание своего заголовка, чем на этот пост, лол. Я надеюсь, что в этом есть смысл.
Я не уверен, возможно ли это, но у меня есть инструкция, в которой мне нужно подсчитать общее количество записей с определенным значением, используя GROUP BY status
и FIELD(status, 'value1', 'value2', 'value3', 'value4', 'value5')
.
Проблема в том, что в моих FIELD
значениях (значение1, значение2…) это значение может не существовать ни в каких записях, поэтому мне нужно, чтобы счетчик возвращал 0
SELECT COUNT(*),status FROM table WHERE some_field = 12345 GROUP BY status ORDER BY FIELD(status, 'value1', 'value2', 'value3', 'value4', 'value5');
ВОЗВРАТ
|COUNT(*)|status|
|3 |value1|
|9 |value2|
|12 |value3|
|34 |value5|
Как вы можете видеть, он отлично подсчитывает все записи, но проблема в том, что ни value4
в одной из записей их нет, поэтому он ничего не возвращает. Что мне нужно, так это вернуться
|COUNT(*)|status|
|3 |value1|
|9 |value2|
|12 |value3|
|0 |value4|
|34 |value5|
Я также возился с IFNULL(COUNT(*), 0)
и IFNULL(status, 0)
, но он возвращает те же результаты с отсутствующим значением. В принципе, мне нужно указать значения, которые я ищу, и вернуть 0, если их нет.
Я также пытался HAVING status = 'value1' OR status = 'value2' OR status = 'value3' OR status = 'value4' OR status = 'value5'
, но добавление этого также не возвращает 0 в отсутствующей строке/значении.
Ответ №1:
Вам нужен запрос, который возвращает 2 столбца: status
нужные вам значения и порядок каждого статуса.
Затем присоедините таблицу к этому запросу с LEFT
помощью объединения и агрегирования:
SELECT s.status, COUNT(t.status) counter
FROM (
SELECT 1 id, 'value1' status UNION ALL
SELECT 2, 'value2' UNION ALL
SELECT 3, 'value3' UNION ALL
SELECT 4, 'value4' UNION ALL
SELECT 5, 'value5'
) s LEFT JOIN tablename t
ON t.status = s.status AND t.some_field = 12345
GROUP BY s.id, s.status
ORDER BY s.id;
Комментарии:
1. Куда мне поместить этот
WHERE
пункт?2. @CesarBielich пункт «ВКЛЮЧЕНО». Смотрите мой отредактированный код.
3. Идеально! Большое спасибо
Ответ №2:
Вы должны присоединиться к полному списку данных
вы можете использовать UNION для всех статусов
SELECT
IFNULL(t1.count_1,0) "count", t2.status
FROM
(SELECT
COUNT(*) count_1, status
FROM
table1
WHERE
some_field = 12345
GROUP BY status
ORDER BY FIELD(status,
'value1',
'value2',
'value3',
'value4',
'value5')) t1
RIGHT JOIN (SELECT
'value1' as status
UNION ALL
SELECT 'value2'
UNION ALL
SELECT 'value3'
UNION ALL
SELECT 'value4'
UNION ALL
SELECT 'value5') st1 on t1.status = st1.status