Conte com a condição IF na consulta MySQL

115

Tenho duas tabelas, uma para notícias e outra para comentários e desejo obter a contagem dos comentários cujo status foi definido como aprovado.

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 

Mas o problema com esta consulta é que o valor mínimo que é buscado para a coluna de comentários é 1 quer haja algum comentário existente correspondente a essa notícia ou não.

Qualquer ajuda seria muito apreciável.

user1163513
fonte
5
E se você usar SUM em vez de COUNT?
John Pick

Respostas:

265

Use sum()no lugar decount()

Experimente abaixo:

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
fonte
11
Ou mesmo SUM (ccc_news_comments.id = 'aprovado') como um truque específico do MySQL
mojuba
1
@mojuba não é 100% igual, seu truque retorna nullquando COUNT(sem condições) teria retornado 0. Quando COUNTteria retornado nada , mas 0, mas o SUM faz de retorno 0, seu truque retornos 0.
Robin Kanters
@mojuba caso e ponto . num_relevant_partsestá SUMcom condições, num_total_partsestá COUNT(parts.id)(desculpe pelo duplo comentário, era tarde demais para editar)
Robin Kanters
68

Melhor ainda (ou mais curto de qualquer maneira):

SUM(ccc_news_comments.id = 'approved')

Isso funciona porque o tipo booleano no MySQL é representado como INT 0e 1, assim como em C. (pode não ser portável em sistemas de banco de dados).

Conforme COALESCE()mencionado em outras respostas, muitas APIs de linguagem são convertidas automaticamente NULLpara ''ao buscar o valor. Por exemplo, com a mysqliinterface do PHP , seria seguro executar sua consulta sem COALESCE().

mojuba
fonte
3
Isso torna o código sql significativamente mais legível. Bela solução.
Dag Sondre Hansen
22

Isso deve funcionar:

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

count()verifique apenas se o valor existe ou não. 0 é equivalente a um valor existente, então ele conta mais um, enquanto NULL é como um valor inexistente, então não é contado.

Edemilson lima
fonte
Acho que counté mais intuitivo do que sumneste caso.
Jeffery
4

Substitua esta linha:

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

Com este:

coalesce(sum(ccc_news_comments.id = 'approved'), 0) comments
Mosty Mostacho
fonte
contagem (if (ccc_news_comments.id = 'aprovado', ccc_news_comments.id, 0)) ??? qual será o significado de usar soma se você usar ccc_news_comments.id
Desculpe oque você quer dizer? O valor booleano torna-se 0 ou 1, então some, e caso haja algum valor nulo, coalescer com 0
Mosty Mostacho
@MostyMostacho, COALESCEdevolve a quantia? Qualquer referência no documento MySQL?
Istiaque Ahmed de
Sim, por que não? Há muitas referências nos documentos: dev.mysql.com/doc/refman/5.7/en/…
Mosty Mostacho