Compter avec la condition IF dans la requête MySQL

115

J'ai deux tableaux, l'un pour les actualités et l'autre pour les commentaires et je veux obtenir le décompte des commentaires dont le statut a été défini comme approuvé.

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 

Mais le problème avec cette requête est que la valeur minimale qui est récupérée pour la colonne de commentaires est 1, qu'il existe un commentaire correspondant à cette nouvelle ou non.

Toute aide serait très appréciable.

user1163513
la source
5
Que faire si vous utilisez SUM au lieu de COUNT?
John Pick

Réponses:

265

Utiliser sum()à la place decount()

Essayez ci-dessous:

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
la source
11
Ou même SUM (ccc_news_comments.id = 'Approuvé') comme astuce spécifique à MySQL
mojuba
1
@mojuba n'est pas à 100% le même, votre astuce revient nullquand COUNT(aucune condition) serait revenue 0. Quand COUNTaurait tout retourné , mais 0, mais le SUM fait retour 0, vos déclarations de truc 0.
Robin Kanters
Cas et point @mojuba . num_relevant_partsest SUMavec conditions, num_total_partsest COUNT(parts.id)(désolé pour le double commentaire, était trop tard pour éditer)
Robin Kanters
68

Mieux encore (ou plus court quand même):

SUM(ccc_news_comments.id = 'approved')

Cela fonctionne puisque le type booléen dans MySQL est représenté par INT 0et 1, tout comme en C. (peut ne pas être portable sur les systèmes de base de données.)

Pour ce qui est COALESCE()mentionné dans d' autres réponses, de nombreuses API de langue convertissent automatiquement NULLà ''lors de la récupération de la valeur. Par exemple, avec l' mysqliinterface de PHP, il serait sûr d'exécuter votre requête sans COALESCE().

mojuba
la source
3
Cela rend le code SQL beaucoup plus lisible. Belle solution.
Dag Sondre Hansen
22

Cela devrait fonctionner:

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

count()vérifier uniquement si la valeur existe ou non. 0 est équivalent à une valeur existante, donc il en compte une de plus, tandis que NULL est comme une valeur inexistante, donc n'est pas compté.

Edemilson Lima
la source
Je pense que countc'est plus intuitif que sumdans ce cas.
Jeffery
4

Remplacez cette ligne:

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

Avec celui-ci:

coalesce(sum(ccc_news_comments.id = 'approved'), 0) comments
Mosty Mostacho
la source
count (if (ccc_news_comments.id = 'approuvé', ccc_news_comments.id, 0)) ??? quel sera le sens de l'utilisation de sum si vous utilisez ccc_news_comments.id
Pardon, que voulez-vous dire? La valeur booléenne devient 0 ou 1, puis somme, et au cas où il y aurait une valeur nulle, fusionner avec 0
Mosty Mostacho
@MostyMostacho, renvoie-t-il COALESCEla somme? Une référence dans la doc MySQL?
Istiaque Ahmed
Oui, pourquoi pas? Il existe de nombreuses références dans la documentation: dev.mysql.com/doc/refman/5.7/en
Mosty Mostacho