sql >> Base de Datos >  >> RDS >> PostgreSQL

Declaración GRUPO POR + CASO

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.