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:
- Generar un conjunto de filas de la(s) tabla(s), incluidas las filas producidas por
JOIN
. - Evaluar
WHERE
condiciones contra el conjunto de filas, filtrando las filas que no coinciden. - Calcule expresiones en la lista de selección para cada una en el conjunto de filas.
- 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).
- Condensar los grupos en una sola fila por grupo, de acuerdo con
GROUP BY
cláusula. - Evaluar
HAVING
condiciones contra grupos, filtrando grupos que no coinciden. - Ordenar resultado, de acuerdo con
ORDER BY
cláusula.