postgresql amazon-redshift

postgresql - En Redshift/Postgres, ¿cómo contar las filas que cumplen una condición?



amazon-redshift (2)

Otro método:

SELECT sum(CASE WHEN grade < 70 THEN 1 else 0 END) as grade_less_than_70, sum(CASE WHEN grade >= 70 and grade < 80 THEN 1 else 0 END) as grade_between_70_and_80 FROM grades

Funciona bien en caso de que quiera agrupar los recuentos por una columna categórica.

Intento escribir una consulta que cuente solo las filas que cumplen una condición.

Por ejemplo, en MySQL lo escribiría así:

SELECT COUNT(IF(grade < 70), 1, NULL) FROM grades ORDER BY id DESC;

Sin embargo, cuando intento hacerlo en Redshift, devuelve el siguiente error:

ERROR: función if (booleano, entero, "desconocido") no existe

Sugerencia: ninguna función coincide con el nombre y los tipos de argumentos. Es posible que necesite agregar moldes de tipo explícitos.

Revisé la documentación en busca de declaraciones condicionales y encontré

NULLIF(value1, value2)

pero solo compara value1 y value2 y si dichos valores son iguales, devuelve null.

No pude encontrar una declaración simple de IF, ya primera vista no pude encontrar una manera de hacer lo que quiero hacer.

Traté de usar la expresión CASE, pero no obtengo los resultados que quiero:

SELECT CASE WHEN grade < 70 THEN COUNT(rank) ELSE COUNT(rank) END FROM grades

Esta es la forma en que quiero contar cosas:

  • fallado (grado <70)

  • promedio (70 <= grado <80)

  • bueno (80 <= grado <90)

  • excelente (90 <= grado <= 100)

y así es como espero ver los resultados:

+========+=========+======+===========+ | failed | average | good | excellent | +========+=========+======+===========+ | 4 | 2 | 1 | 4 | +========+=========+======+===========+

pero estoy obteniendo esto:

+========+=========+======+===========+ | failed | average | good | excellent | +========+=========+======+===========+ | 11 | 11 | 11 | 11 | +========+=========+======+===========+

¡Espero que alguien pueda señalarme en la dirección correcta!

Si esto ayuda aquí hay alguna información de muestra

CREATE TABLE grades( grade integer DEFAULT 0, ); INSERT INTO grades(grade) VALUES(69, 50, 55, 60, 75, 70, 87, 100, 100, 98, 94);


Primero, el problema que está teniendo aquí es que lo que está diciendo es "Si la calificación es menor a 70, el valor de esta expresión de caso es recuento (rango). De lo contrario, el valor de esta expresión es recuento (rango) " Entonces, en cualquier caso, siempre obtienes el mismo valor.

SELECT CASE WHEN grade < 70 THEN COUNT(rank) ELSE COUNT(rank) END FROM grades

count () solo cuenta valores que no son nulos, por lo que el patrón que verás para lograr lo que intentas es el siguiente:

SELECT count(CASE WHEN grade < 70 THEN 1 END) as grade_less_than_70, count(CASE WHEN grade >= 70 and grade < 80 THEN 1 END) as grade_between_70_and_80 FROM grades

De esta forma, la expresión de caso solo evaluará a 1 cuando la expresión de prueba sea verdadera y será nula de lo contrario. Entonces el recuento () solo contará las instancias no nulas, es decir, cuando la expresión de prueba sea verdadera, lo que le proporcionará lo que necesita.

Editar: Como nota al margen, observe que esto es exactamente igual a cómo lo había escrito originalmente utilizando el count(if(test, true-value, false-value)) , solo se vuelve a escribir como count(case when test then true-value end) (y null es el soporte en falso-valor ya else no se suministró un else al caso).

Editar: postgres 9.4 fue lanzado unos meses después de este intercambio original. Esa versión introdujo filtros agregados, que pueden hacer que los escenarios como este se vean un poco más claros y claros. Esta respuesta todavía recibe algunos votos a favor ocasionales, por lo que si te has encontrado con un postgres más reciente (es decir, 9.4 o superior), quizás quieras considerar esta versión equivalente:

SELECT count(*) filter (where grade < 70) as grade_less_than_70, count(*) filter (where grade >= 70 and grade < 80) as grade_between_70_and_80 FROM grades