Подсчет с условием IF в запросе MySQL

116

У меня есть две таблицы, одна для новостей, а другая для комментариев, и я хочу получить количество комментариев, статус которых был установлен как одобренный.

SELECT
    ccc_news . *, 
    count(if(ccc_news_comments.id = 'approved', ccc_news_comments.id, 0)) AS comments
FROM
    ccc_news
    LEFT JOIN
        ccc_news_comments
    ON ccc_news_comments.news_id = ccc_news.news_id
WHERE
    `ccc_news`.`category` = 'news_layer2'
    AND `ccc_news`.`status` = 'Active'
GROUP BY
    ccc_news.news_id
ORDER BY
    ccc_news.set_order ASC
LIMIT 20 

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

Любая помощь будет очень заметна.

user1163513
источник
5
Что делать, если вместо COUNT использовать SUM?
John Pick

Ответы:

267

Использовать sum()вместоcount()

Попробуйте ниже:

SELECT
    ccc_news . * , 
    SUM(if(ccc_news_comments.id = 'approved', 1, 0)) AS comments
FROM
    ccc_news
    LEFT JOIN
        ccc_news_comments
    ON
        ccc_news_comments.news_id = ccc_news.news_id
WHERE
    `ccc_news`.`category` = 'news_layer2'
    AND `ccc_news`.`status` = 'Active'
GROUP BY
    ccc_news.news_id
ORDER BY
    ccc_news.set_order ASC
LIMIT 20 
ElChiniNet
источник
11
Или даже SUM (ccc_news_comments.id = 'authorized') как специфичный для MySQL трюк
mojuba
1
@mojuba не на 100% то же самое, ваш трюк возвращается, nullкогда COUNT(без условий) вернется 0. Когда COUNTбы я вернулся ничего , кроме 0, но SUM делает возврат 0, ваш трюк возвращается 0.
Робин Кантерс
@mojuba случай и точка . num_relevant_partsесть SUMс условиями, num_total_partsявляется COUNT(parts.id)(извините за двойной комментарий, было слишком поздно , чтобы редактировать)
Robin Кантеры
68

Еще лучше (или короче):

SUM(ccc_news_comments.id = 'approved')

Это работает, поскольку логический тип в MySQL представлен как INT 0и 1, как и в C. (хотя может не переноситься в системы БД).

Что касается, COALESCE()как упоминалось в других ответах, многие языковые API автоматически конвертируются NULLв ''при извлечении значения. Например, с mysqliинтерфейсом PHP было бы безопасно выполнять ваш запрос без COALESCE().

mojuba
источник
3
Это делает код sql значительно более читаемым. Красивое решение.
Даг Сондре Хансен
22

Это должно работать:

count(if(ccc_news_comments.id = 'approved', ccc_news_comments.id, NULL))

count()только проверьте, существует ли значение или нет. 0 эквивалентно существующему значению, поэтому он учитывает еще одно, в то время как NULL похож на несуществующее значение, поэтому не учитывается.

Эдемилсон Лима
источник
Я считаю countболее интуитивным, чем sumв этом случае.
Джеффри
4

Замените эту строку:

count(if(ccc_news_comments.id = 'approved', ccc_news_comments.id, 0)) AS comments

С этим:

coalesce(sum(ccc_news_comments.id = 'approved'), 0) comments
Мосты Мостачо
источник
количество (если (ccc_news_comments.id = 'утверждено', ccc_news_comments.id, 0)) ??? какой будет смысл использования суммы, если вы используете ccc_news_comments.id
Извини, что ты имеешь ввиду? Логическое значение становится 0 или 1, затем суммируется, и в случае слияния некоторого нулевого значения с 0
Mosty Mostacho
@MostyMostacho, COALESCEвозвращает ли сумму? Любая ссылка в документе MySQL?
Istiaque Ahmed
Да почему бы и нет? В документации много ссылок: dev.mysql.com/doc/refman/5.7/en/…
Мосты Мостачо