Su consulta ya funcionaría, excepto que tiene conflictos de nombres o simplemente confunde la columna de salida (el CASE
expresión) con columna de origen result
, que tiene un contenido diferente.
...
GROUP BY model.name, attempt.type, attempt.result
...
Necesitas GROUP BY
tu CASE
expresión en lugar de su columna de origen:
...
GROUP BY model.name, attempt.type
, CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END
...
O proporcione un alias de columna eso es diferente de cualquier nombre de columna en el FROM
lista - o bien esa columna tiene prioridad:
SELECT ...
, CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END AS result1
...
GROUP BY model.name, attempt.type, result1
...
El estándar SQL es bastante peculiar a este respecto. Citando el manual aquí:
El nombre de una columna de salida se puede usar para hacer referencia al valor de la columna en ORDER BY
y GROUP BY
cláusulas, pero no en el WHERE
o HAVING
cláusulas; allí debe escribir la expresión en su lugar.
Y:
Si un ORDER BY
expresión es un nombre simple que coincide con un nombre de columna de salida y un nombre de columna de entrada, ORDER BY
lo interpretará como el nombre de la columna de salida. Esta es la opción opuesta a la que GROUP BY
hará en la misma situación. Esta inconsistencia está hecha para ser compatible con el estándar SQL.
Negrita énfasis mío.
Estos conflictos se pueden evitar usando referencias posicionales (números ordinales) en GROUP BY
y ORDER BY
, haciendo referencia a elementos en el SELECT
lista de izquierda a derecha. Vea la solución a continuación.
El inconveniente es que esto puede ser más difícil de leer y vulnerable a las ediciones en SELECT
list (uno podría olvidarse de adaptar las referencias posicionales en consecuencia).
Pero tú no hay que agregar la columna day
al GROUP BY
cláusula, siempre que contenga un valor constante (CURRENT_DATE-1
).
Reescrito y simplificado con la sintaxis JOIN adecuada y las referencias posicionales, podría tener este aspecto:
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;
También tenga en cuenta que estoy evitando el nombre de columna time
. Esa es una palabra reservada y nunca debe usarse como identificador. Además, tu "hora" obviamente es una timestamp
o date
, por lo que es bastante engañoso.