Как получить значение COUNT (), когда в GROUP BY нет строки? - PullRequest
1 голос
/ 09 марта 2020

RDMS : MariaDB 10.1.23

MCRE:

create table entity
(
    id_entity int auto_increment,
    created_at timestamp default CURRENT_TIMESTAMP,
    constraint product_log_pk
        primary key (id_entity)
);

INSERT INTO entity SET created_at = CURRENT_TIMESTAMP;
INSERT INTO entity SET created_at = CURRENT_TIMESTAMP;
INSERT INTO entity SET created_at = CURRENT_TIMESTAMP;

-- I would like this to return 0
SELECT IF(COUNT(e.id_entity) = 0, 0, e.id_entity) 
FROM entity e
WHERE e.created_at < CURRENT_DATE - INTERVAL 1 DAY GROUP BY e.created_at;

SQLFiddle: http://sqlfiddle.com/#! 9 / f32a01 / 1


Рассмотрим следующий запрос:

SELECT IF(COUNT(e.some_field) = 0, 0, e.some_field) 
FROM entity e
WHERE e.created_at > CURRENT_DATE - INTERVAL 1 DAY GROUP BY e.created_at

Без предложения GROUP BY я знаю, что COUNT() вернет 0, если ни одна строка не соответствует запросу.

Я также знаю, что, если мой GROUP BY "потерпит неудачу" (если у меня нет строки для группировки, в моем примере, если ни одна строка не удовлетворяет e.created_at > CURRENT_DATE - INTERVAL 1 DAY), то COUNT () не будет ничего возвращать ( 0 ряд). Как я могу убедиться, что COUNT () возвращает 0 (1 строка со значением 0) в этом случае?

Ответы [ 3 ]

2 голосов
/ 09 марта 2020

Группировка выполняется после оценки предложения; если предложение where удаляет все строки, то группировать нечего.

Я предполагаю, что вам нужна условная агрегация. Вот пример:

name | dept | gender
-----+------+-------
jane | acc  | f
john | acc  | m
jack | hr   | m
jake | hr   | m

И запрос на подсчет всех сотрудников женского пола по отделам:

SELECT dept, COUNT(CASE WHEN gender = 'f' THEN 1 END)
FROM employee
-- WHERE gender = ... will/could eliminate entire group(s)
GROUP BY dept
dept | count
-----+------
acc  | 1
hr   | 0
1 голос
/ 24 марта 2020

«Стандартный» способ -

 COALESCE(value, 0)

Обычно используется следующим образом:

COALESCE( ( SELECT COUNT(*) ... ), 0)
1 голос
/ 09 марта 2020

Кажется, вы заботитесь только об одном ряду. Для этого просто удалите GROUP BY.

Я понятия не имею, что должен делать IF()

SELECT COUNT(e.some_field)
FROM entity e
WHERE e.created_at > CURRENT_DATE - INTERVAL 1 DAY ;

Если вы хотите вернуть значения i some_field тогда GROUP_CONCAT() поместит их все в один столбец:

SELECT GROUP_CONCAT(e.some_field)
FROM entity e
WHERE e.created_at > CURRENT_DATE - INTERVAL 1 DAY ;

Оба эти всегда возвращают одну строку, потому что это агрегационные запросы без GROUP BY. Первый возвращает 0, а второй NULL, если не найдено ни одной строки.

...