La tua query funzionerebbe già, tranne per il fatto che stai riscontrando conflitti di denominazione o semplicemente confondendo la colonna di output (il CASE
espressione) con colonna sorgente result
, che ha contenuti diversi.
...
GROUP BY model.name, attempt.type, attempt.result
...
Devi GROUP BY
il tuo CASE
espressione invece della colonna di origine:
...
GROUP BY model.name, attempt.type
, CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END
...
Oppure fornisci un alias di colonna è diverso da qualsiasi nome di colonna nel FROM
list - oppure quella colonna ha la precedenza:
SELECT ...
, CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END AS result1
...
GROUP BY model.name, attempt.type, result1
...
Lo standard SQL è piuttosto peculiare a questo riguardo. Citando il manuale qui:
Il nome di una colonna di output può essere utilizzato per fare riferimento al valore della colonna inORDER BY
e GROUP BY
clausole, ma non in WHERE
o HAVING
clausole; lì devi invece scrivere l'espressione.
E:
Se un ORDER BY
espressione è un nome semplice che corrisponde sia a un nome di colonna di output che a un nome di colonna di input, ORDER BY
lo interpreterà come il nome della colonna di output. Questo è l'opposto della scelta che GROUP BY
farà nella stessa situazione. Questa incoerenza è resa compatibile con lo standard SQL.
Grassetto enfasi mia.
Questi conflitti possono essere evitati utilizzando riferimenti posizionali (numeri ordinali) in GROUP BY
e ORDER BY
, facendo riferimento agli elementi in SELECT
elenco da sinistra a destra. Vedi la soluzione di seguito.
Lo svantaggio è che potrebbe essere più difficile da leggere e vulnerabile alle modifiche nel SELECT
list (si potrebbe dimenticare di adattare i riferimenti posizionali di conseguenza).
Ma tu non aggiungere la colonna day
al GROUP BY
clausola, purché contenga un valore costante (CURRENT_DATE-1
).
Riscritto e semplificato con una corretta sintassi JOIN e riferimenti posizionali potrebbe apparire così:
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;
Nota anche che sto evitando il nome della colonna time
. Questa è una parola riservata e non dovrebbe mai essere usata come identificatore. Inoltre, il tuo "tempo" ovviamente è un timestamp
o date
, quindi è piuttosto fuorviante.