使用 OVER(PARTITION BY) 限制分区中的结果数

Nyx*_*nyx 6 postgresql postgis postgresql-9.1

在下面的查询中,为什么我们必须使用WHERE foo.row_num < 3子查询之外的子句foo而不是子查询内的子句来限制从每个 Partition 返回的结果WHERE row_num < 3

询问

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;
Run Code Online (Sandbox Code Playgroud)

不工作的查询

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;
Run Code Online (Sandbox Code Playgroud)

错误: ERROR: column "row_num" does not exist

Mik*_*ll' 4

列“row_num”不存在,因为处理的逻辑顺序要求 dbms在计算 SELECT 子句之前应用 WHERE 子句。窗口函数是 SELECT 子句的一部分,因此在同一语句的 WHERE 子句中无法访问其别名。

FROM 子句是要计算的语句的第一个部分。这就是为什么您在 FROM 子句中声明的别名可以在同一语句的 WHERE 子句中访问。

在此页面中搜索“逻辑处理顺序”。尽管这链接到 SQL Server 文档,但对于每个符合 SQL 标准的 dbms,处理的逻辑顺序是相同的。