Mysql
 sql >> Base de données >  >> RDS >> Mysql

Requête :compter plusieurs agrégats par élément

Voici une astuce :calculer un SUM() de valeurs connues pour être 1 ou 0 équivaut à un COUNT() des lignes où la valeur est 1. Et vous savez qu'une comparaison booléenne renvoie 1 ou 0 (ou NULL).

SELECT c.catname, COUNT(m.catid) AS item_count,
  SUM(i.ownerid = @ownerid) AS owner_item_count
FROM categories c
  LEFT JOIN map m USING (catid)
  LEFT JOIN items i USING (itemid)
GROUP BY c.catid;

En ce qui concerne la question bonus, vous pouvez simplement faire une jointure interne au lieu d'une jointure externe, ce qui signifierait uniquement des catégories avec au moins une ligne dans map serait retourné.

SELECT c.catname, COUNT(m.catid) AS item_count,
  SUM(i.ownerid = @ownerid) AS owner_item_count
FROM categories c
  INNER JOIN map m USING (catid)
  INNER JOIN items i USING (itemid)
GROUP BY c.catid;

Voici une autre solution, qui n'est pas aussi efficace mais je vais la montrer pour expliquer pourquoi vous avez l'erreur :

SELECT c.catname, COUNT(m.catid) AS item_count,
  SUM(i.ownerid = @ownerid) AS owner_item_count
FROM categories c
  LEFT JOIN map m USING (catid)
  LEFT JOIN items i USING (itemid)
GROUP BY c.catid
HAVING item_count > 0;

Vous ne pouvez pas utiliser d'alias de colonne dans WHERE clause, car les expressions dans WHERE clause sont évaluées avant les expressions dans la liste de sélection. En d'autres termes, les valeurs associées aux expressions de liste de sélection ne sont pas encore disponibles.

Vous pouvez utiliser des alias de colonne dans le GROUP BY , HAVING , et ORDER BY clauses. Ces clauses sont exécutées après que toutes les expressions de la liste de sélection ont été évaluées.