Uw zoekopdracht zou al werken, behalve dat u naamconflicten tegenkomt of gewoon de uitvoerkolom verwart (de CASE
expressie) met bronkolom result
, die andere inhoud heeft.
...
GROUP BY model.name, attempt.type, attempt.result
...
U moet GROUP BY
uw CASE
expressie in plaats van uw bronkolom:
...
GROUP BY model.name, attempt.type
, CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END
...
Of geef een kolomalias dat is anders dan elke kolomnaam in de FROM
lijst - anders heeft die kolom voorrang:
SELECT ...
, CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END AS result1
...
GROUP BY model.name, attempt.type, result1
...
De SQL-standaard is in dit opzicht nogal eigenaardig. Ik citeer hier de handleiding:
De naam van een uitvoerkolom kan worden gebruikt om te verwijzen naar de waarde van de kolom in
ORDER BY
enGROUP BY
clausules, maar niet in deWHERE
ofHAVING
clausules; daar moet u in plaats daarvan de uitdrukking uitschrijven.
En:
Als een
ORDER BY
expressie is een eenvoudige naam die overeenkomt met zowel een uitvoerkolomnaam als een invoerkolomnaam,ORDER BY
zal het interpreteren als de naam van de uitvoerkolom. Dit is het tegenovergestelde van de keuze dieGROUP BY
zal maken in dezelfde situatie. Deze inconsistentie is gemaakt om compatibel te zijn met de SQL-standaard.
Vet benadruk de mijne.
Deze conflicten kunnen worden vermeden door gebruik te maken van positionele verwijzingen (volgnummers) in GROUP BY
en ORDER BY
, verwijzend naar items in de SELECT
lijst van links naar rechts. Zie de oplossing hieronder.
Het nadeel is dat dit moeilijker te lezen en kwetsbaarder kan zijn voor bewerkingen in de SELECT
lijst (men zou kunnen vergeten positionele referenties dienovereenkomstig aan te passen).
Maar jij niet moet de kolom day
. toevoegen naar de GROUP BY
clausule, zolang deze een constante waarde heeft (CURRENT_DATE-1
).
Herschreven en vereenvoudigd met de juiste JOIN-syntaxis en positionele verwijzingen zou het er als volgt uit kunnen zien:
SELECT m.name
, a.type
, CASE WHEN a.result = 0 THEN 0 ELSE 1 END AS result
, CURRENT_DATE - 1 AS day
, count(*) AS ct
FROM attempt a
JOIN prod_hw_id p USING (hard_id)
JOIN model m USING (model_id)
WHERE ts >= '2013-11-06 00:00:00'
AND ts < '2013-11-07 00:00:00'
GROUP BY 1,2,3
ORDER BY 1,2,3;
Merk ook op dat ik de kolomnaam time
vermijd . Dat is een gereserveerd woord en mag nooit als identifier worden gebruikt. Trouwens, je "tijd" is duidelijk een timestamp
of date
, dus dat is nogal misleidend.