Oto sztuczka:obliczanie SUM()
wartości, o których wiadomo, że są równe 1 lub 0, jest równoważne COUNT()
wierszy, w których wartość wynosi 1. I wiesz, że porównanie logiczne zwraca 1 lub 0 (lub 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;
Jeśli chodzi o dodatkowe pytanie, możesz po prostu wykonać sprzężenie wewnętrzne zamiast sprzężenia zewnętrznego, co oznaczałoby tylko kategorie z co najmniej jednym wierszem w map
zostanie zwrócony.
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;
Oto inne rozwiązanie, które nie jest tak wydajne, ale pokażę je, aby wyjaśnić, dlaczego wystąpił błąd:
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;
Nie możesz używać aliasów kolumn w WHERE
klauzula, ponieważ wyrażenia w WHERE
klauzule są oceniane przed wyrażeniami na liście wyboru. Innymi słowy, wartości powiązane z wyrażeniami listy wyboru nie są jeszcze dostępne.
Możesz używać aliasów kolumn w GROUP BY
, HAVING
i ORDER BY
klauzule. Klauzule te są uruchamiane po przeanalizowaniu wszystkich wyrażeń z listy wyboru.