Использование ПОДСЧЕТА с ГРУППИРОВАНИЕМ ПО и подсчетом строк ПОЛЕЙ, в которых значение не существует

#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