Cuente con la condición IF en la consulta MySQL

115

Tengo dos tablas, una es para noticias y la otra para comentarios y quiero obtener el recuento de los comentarios cuyo estado se ha establecido como aprobado.

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 

Pero el problema con esta consulta es que el valor mínimo que se obtiene para la columna de comentarios es 1, ya sea que exista algún comentario correspondiente a esa noticia o no.

Cualquier ayuda sería muy apreciada.

usuario1163513
fuente
5
¿Qué pasa si usa SUM en lugar de COUNT?
John Pick

Respuestas:

265

Usar sum()en lugar decount()

Prueba a continuación:

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
fuente
11
O incluso SUM (ccc_news_comments.id = 'aprobado') como un truco específico de MySQL
mojuba
1
@mojuba no es 100% igual, tu truco regresa nullcuando COUNT(sin condiciones) hubiera regresado 0. Cuando COUNTse habría devuelto nada , pero 0, pero la SUM hace de retorno 0, sus declaraciones de truco 0.
Robin Kanters
@mojuba caso y punto . num_relevant_partses SUMcon condiciones, num_total_partses COUNT(parts.id)(perdón por el doble comentario, era demasiado tarde para editar)
Robin Kanters
68

Mejor aún (o más corto de todos modos):

SUM(ccc_news_comments.id = 'approved')

Esto funciona ya que el tipo booleano en MySQL se representa como INT 0y 1, al igual que en C. (aunque puede que no sea portátil en sistemas de base de datos).

En cuanto a COALESCE()como se ha mencionado en otras respuestas, muchas API de lenguaje convierten automáticamente NULLal ''cual se deben recuperar el valor. Por ejemplo, con la mysqliinterfaz de PHP sería seguro ejecutar su consulta sin COALESCE().

mojuba
fuente
3
Esto hace que el código sql sea significativamente más legible. Hermosa solución.
Dag Sondre Hansen
22

Esto debería funcionar:

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

count()solo verifique si el valor existe o no. 0 es equivalente a un valor existente, por lo que cuenta uno más, mientras que NULL es como un valor inexistente, por lo que no se cuenta.

Edemilson Lima
fuente
Creo que countes más intuitivo que sumen este caso.
Jeffery
4

Reemplazar esta línea:

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

Con este:

coalesce(sum(ccc_news_comments.id = 'approved'), 0) comments
Mosty Mostacho
fuente
contar (si (ccc_news_comments.id = 'aprobado', ccc_news_comments.id, 0)) ??? cuál será el significado de usar sum si usa ccc_news_comments.id
¿Lo siento, qué quieres decir? El valor booleano se convierte en 0 o 1, luego suma, y ​​en caso de que haya algún valor nulo se fusiona con 0
Mosty Mostacho
@MostyMostacho, ¿ COALESCEdevuelve la suma? ¿Alguna referencia en el documento de MySQL?
Istiaque Ahmed
Sí, ¿por qué no lo haría? Hay muchas referencias en los documentos: dev.mysql.com/doc/refman/5.7/en/…
Mosty Mostacho