Din fråga skulle redan fungera - förutom att du stöter på namnkonflikter eller bara förvirrar utdatakolumnen (CASE
uttryck) med källkolumnen result
, som har annat innehåll.
...
GROUP BY model.name, attempt.type, attempt.result
...
Du måste GROUP BY
ditt CASE
uttryck istället för din källkolumn:
...
GROUP BY model.name, attempt.type
, CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END
...
Eller ange ett kolumnalias som skiljer sig från alla kolumner i FROM
lista - annars har den kolumnen företräde:
SELECT ...
, CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END AS result1
...
GROUP BY model.name, attempt.type, result1
...
SQL-standarden är ganska speciell i detta avseende. Citerar manualen här:
En utdatakolumns namn kan användas för att referera till kolumnens värde i
ORDER BY
ochGROUP BY
satser, men inte iWHERE
ellerHAVING
klausuler;där måste du skriva ut uttrycket istället.
Och:
Om en
ORDER BY
expression är ett enkelt namn som matchar både ett utdatakolumnnamn och ett indatakolumnnamn,ORDER BY
kommer att tolka det som utdatakolumnnamnet. Detta är motsatsen till valet somGROUP BY
kommer att göra i samma situation. Denna inkonsekvens görs för att vara kompatibel med SQL-standarden.
Fet betoning min.
Dessa konflikter kan undvikas genom att använda positionsreferenser (ordningstal) i GROUP BY
och ORDER BY
, hänvisar till objekt i SELECT
lista från vänster till höger. Se lösningen nedan.
Nackdelen är att detta kan vara svårare att läsa och sårbart för redigeringar i SELECT
lista (man kan glömma att anpassa positionsreferenser därefter).
Men det gör du inte måste lägga till kolumnen day
till GROUP BY
sats, så länge den har ett konstant värde (CURRENT_DATE-1
).
Omskrivet och förenklat med korrekt JOIN-syntax och positionsreferenser kan det se ut så här:
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;
Observera också att jag undviker kolumnnamnet time
. Det är ett reserverat ord och bör aldrig användas som identifierare. Dessutom är din "tid" uppenbarligen en timestamp
eller date
, så det är ganska missvisande.