Sua consulta já funcionaria - exceto que você está enfrentando conflitos de nomenclatura ou apenas confundindo a coluna de saída (o
CASE
expressão) com coluna de origem result
, que tem conteúdo diferente. ...
GROUP BY model.name, attempt.type, attempt.result
...
Você precisa
GROUP BY
seu CASE
expressão em vez de sua coluna de origem:...
GROUP BY model.name, attempt.type
, CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END
...
Ou forneça um alias de coluna que é diferente de qualquer nome de coluna no
FROM
list - ou então essa coluna tem precedência:SELECT ...
, CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END AS result1
...
GROUP BY model.name, attempt.type, result1
...
O padrão SQL é bastante peculiar a esse respeito. Citando o manual aqui:
O nome de uma coluna de saída pode ser usado para se referir ao valor da coluna emORDER BY
eGROUP BY
cláusulas, mas não noWHERE
ouHAVING
cláusulas; lá você deve escrever a expressão.
E:
Se umORDER BY
expressão é um nome simples que corresponde a um nome de coluna de saída e a um nome de coluna de entrada,ORDER BY
irá interpretá-lo como o nome da coluna de saída. Isso é o oposto da escolha queGROUP BY
fará na mesma situação. Essa inconsistência é feita para ser compatível com o padrão SQL.
Negrito ênfase minha.
Esses conflitos podem ser evitados usando referências posicionais (números ordinais) em
GROUP BY
e ORDER BY
, referenciando itens no SELECT
lista da esquerda para a direita. Veja a solução abaixo.A desvantagem é que isso pode ser mais difícil de ler e vulnerável a edições no
SELECT
list (pode-se esquecer de adaptar as referências posicionais de acordo). Mas você não tem que adicionar a coluna
day
para o GROUP BY
cláusula, desde que mantenha um valor constante (CURRENT_DATE-1
). Reescrito e simplificado com a sintaxe JOIN adequada e referências posicionais, poderia ficar assim:
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;
Observe também que estou evitando o nome da coluna
time
. Essa é uma palavra reservada e nunca deve ser usada como identificador. Além disso, seu "tempo" obviamente é um timestamp
ou date
, de modo que é bastante enganador.