Din forespørgsel ville allerede virke - bortset fra at du løber ind i navnekonflikter eller bare forvirrer outputkolonnen (CASE
udtryk) med kildekolonnen result
, som har forskelligt indhold.
...
GROUP BY model.name, attempt.type, attempt.result
...
Du skal GROUP BY
din CASE
udtryk i stedet for din kildekolonne:
...
GROUP BY model.name, attempt.type
, CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END
...
Eller angiv et kolonnealias det er forskelligt fra et hvilket som helst kolonnenavn i FROM
liste - ellers har den kolonne forrang:
SELECT ...
, CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END AS result1
...
GROUP BY model.name, attempt.type, result1
...
SQL-standarden er ret ejendommelig i denne henseende. Citerer manualen her:
En outputkolonnes navn kan bruges til at henvise til kolonnens værdi iORDER BY
og GROUP BY
klausuler, men ikke i WHERE
eller HAVING
klausuler;der skal du skrive udtrykket ud i stedet.
Og:
Hvis en ORDER BY
udtryk er et simpelt navn, der matcher både et outputkolonnenavn og et inputkolonnenavn, ORDER BY
vil fortolke det som outputkolonnenavnet. Dette er det modsatte af valget GROUP BY
vil gøre i samme situation. Denne inkonsistens er lavet for at være kompatibel med SQL-standarden.
Fed vægt min.
Disse konflikter kan undgås ved at bruge positionelle referencer (ordenstal) i GROUP BY
og ORDER BY
, der henviser til elementer i SELECT
liste fra venstre mod højre. Se løsningen nedenfor.
Ulempen er, at dette kan være sværere at læse og sårbart over for redigeringer i SELECT
liste (man kan glemme at tilpasse positionsreferencer i overensstemmelse hermed).
Men det gør du ikke skal tilføje kolonnen day
til GROUP BY
klausul, så længe den har en konstant værdi (CURRENT_DATE-1
).
Omskrevet og forenklet med korrekt JOIN-syntaks og positionsreferencer kunne det se sådan ud:
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;
Bemærk også, at jeg undgår kolonnenavnet time
. Det er et reserveret ord og bør aldrig bruges som identifikator. Desuden er din "tid" naturligvis et timestamp
eller date
, så det er ret misvisende.