Na consulta a seguir, por que temos que limitar os resultados retornados de cada partição usando a cláusula WHERE foo.row_num < 3
fora da subconsulta foo
, mas não dentro da subconsulta com WHERE row_num < 3
?
Consulta
SELECT pid, land_type, row_num, road_name, round(CAST(dist_km AS numeric), 2) AS dist_km
FROM (
SELECT ROW_NUMBER()
OVER (
PARTITION by loc.pid
ORDER BY ST_Distance(r.the_geom, loc.the_geom)
) as row_num,
loc.pid, loc.land_type, r.road_name,
ST_Distance(r.the_geom, loc.the_geom)/1000 as dist_km
FROM ch05.land AS loc
LEFT JOIN ch05.road AS r
ON ST_DWithin(r.the_geom, loc.the_geom, 1000)
WHERE loc.land_type = 'police station'
) AS foo
WHERE foo.row_num < 3
ORDER BY pid, row_num;
Consulta que não funciona
SELECT pid, land_type, row_num, road_name, round(CAST(dist_km AS numeric), 2) AS dist_km
FROM (
SELECT ROW_NUMBER()
OVER (
PARTITION by loc.pid
ORDER BY ST_Distance(r.the_geom, loc.the_geom)
) as row_num,
loc.pid, loc.land_type, r.road_name,
ST_Distance(r.the_geom, loc.the_geom)/1000 as dist_km
FROM ch05.land AS loc
LEFT JOIN ch05.road AS r
ON ST_DWithin(r.the_geom, loc.the_geom, 1000)
WHERE loc.land_type = 'police station'
AND row_num < 3
) AS foo
ORDER BY pid, row_num;
Erro: ERROR: column "row_num" does not exist
A coluna "row_num" não existe porque a ordem lógica de processamento exige que o dbms aplique a cláusula WHERE antes de avaliar a cláusula SELECT. A função de janelamento faz parte da cláusula SELECT, portanto, seu alias não é acessível na cláusula WHERE da mesma instrução.
A cláusula FROM é a primeira parte da instrução a ser avaliada. É por isso que os aliases que você declara na cláusula FROM são acessíveis na cláusula WHERE da mesma instrução.
Pesquise nesta página por "ordem de processamento lógico". Embora esteja vinculado à documentação do SQL Server, a ordem lógica de processamento é a mesma para todos os dbms que estão em conformidade com os padrões SQL.