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

PostgreSQL:¿falla la subconsulta correlacionada?

Algunos puntos importantes sobre el uso de SQL:

  • No puede usar alias de columna en la cláusula WHERE, pero puede hacerlo en la cláusula HAVING. Esa es la causa del error que obtuviste.
  • Puede hacer su conteo mejor usando JOIN y GROUP BY que usando subconsultas correlacionadas. Será mucho más rápido.
  • Utilice la cláusula HAVING para filtrar grupos.

Esta es la forma en que escribiría esta consulta:

SELECT t1.id, COUNT(t2.id) AS num_things
FROM t1 JOIN t2 USING (id)
GROUP BY t1.id
HAVING num_things = 5;

Me doy cuenta de que esta consulta puede omitir JOIN con t1, como en la solución de Charles Bretana. Pero supongo que querrá que la consulta incluya algunas otras columnas de t1.

Re:la pregunta en el comentario:

La diferencia es que el WHERE la cláusula se evalúa en filas, antes de GROUP BY reduce los grupos a una sola fila por grupo. El HAVING La cláusula se evalúa después de que se forman los grupos. Por lo tanto, no puede, por ejemplo, cambiar el COUNT() de un grupo usando HAVING; solo puede excluir el grupo en sí.

SELECT t1.id, COUNT(t2.id) as num
FROM t1 JOIN t2 USING (id)
WHERE t2.attribute = <value>
GROUP BY t1.id
HAVING num > 5;

En la consulta anterior, WHERE filtra las filas que coinciden con una condición y HAVING filtros para grupos que tienen al menos cinco recuentos.

El punto que causa confusión a la mayoría de las personas es cuando no tienen un GROUP BY cláusula, por lo que parece como HAVING y WHERE son intercambiables.

WHERE se evalúa antes que las expresiones en la lista de selección. Esto puede no ser obvio porque la sintaxis SQL pone la lista de selección primero. Por lo tanto, puede ahorrar una gran cantidad de cálculos costosos utilizando WHERE para restringir filas.

SELECT <expensive expressions>
FROM t1
HAVING primaryKey = 1234;

Si usa una consulta como la anterior, las expresiones en la lista de selección se calculan para cada fila , solo para descartar la mayoría de los resultados debido a HAVING condición. Sin embargo, la consulta a continuación calcula la expresión solo para la fila única haciendo coincidir el WHERE condición.

SELECT <expensive expressions>
FROM t1
WHERE primaryKey = 1234;

En resumen, el motor de la base de datos ejecuta las consultas de acuerdo con una serie de pasos:

  1. Generar un conjunto de filas de la(s) tabla(s), incluidas las filas producidas por JOIN .
  2. Evaluar WHERE condiciones contra el conjunto de filas, filtrando las filas que no coinciden.
  3. Calcule expresiones en la lista de selección para cada una en el conjunto de filas.
  4. Aplicar alias de columna (tenga en cuenta que este es un paso aparte, lo que significa que no puede usar alias en expresiones en la lista de selección).
  5. Condensar los grupos en una sola fila por grupo, de acuerdo con GROUP BY cláusula.
  6. Evaluar HAVING condiciones contra grupos, filtrando grupos que no coinciden.
  7. Ordenar resultado, de acuerdo con ORDER BY cláusula.