Her er et trick:at beregne en SUM()
af værdier, der vides at være enten 1 eller 0, svarer til en COUNT()
af rækkerne, hvor værdien er 1. Og du ved, at en boolesk sammenligning returnerer 1 eller 0 (eller 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;
Med hensyn til bonusspørgsmålet kan du simpelthen lave en indre joinforbindelse i stedet for en ydre joinforbindelse, hvilket kun vil betyde kategorier med mindst én række i map
ville blive returneret.
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;
Her er en anden løsning, som ikke er så effektiv, men jeg vil vise den for at forklare, hvorfor du fik fejlen:
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;
Du kan ikke bruge kolonnealiasser i WHERE
klausul, fordi udtryk i WHERE
klausul evalueres før udtrykkene i valglisten. Med andre ord er de værdier, der er knyttet til valglisteudtryk, ikke tilgængelige endnu.
Du kan bruge kolonnealiasser i GROUP BY
, HAVING
, og ORDER BY
klausuler. Disse klausuler køres, efter at alle udtryk i valglisten er blevet evalueret.