如何在仅支持有限SQL的File Geodatabase中筛选人口前4的城市?
File Geodatabase的SQL限制与Top-N查询实现
数据库SQL支持情况
不支持的功能
- 窗口函数(Window Functions)
- TOP、LIMIT、FETCH FIRST 或 ROWNUM 语法
- 关联子查询
支持的功能
- 标量子查询
- 派生表
- GROUP BY、ORDER BY、JOIN 等基础语法
- File Geodatabase的SQL报告与分析
- ArcGIS查询表达式SQL参考
测试数据
我有一个CITIES表,结构与数据如下:
create table cities ( objectid int, population_centre varchar2(255), population_2021 number(38,1), other_columns varchar2(255) ); insert into cities (objectid,population_centre,population_2021,other_columns) values (11,'Calgary',1305550,'a'); insert into cities (objectid,population_centre,population_2021,other_columns) values (23,'Edmonton',1151635,'b'); insert into cities (objectid,population_centre,population_2021,other_columns) values (31,'Halifax',348634,'c'); insert into cities (objectid,population_centre,population_2021,other_columns) values (32,'Hamilton',729560,'d'); insert into cities (objectid,population_centre,population_2021,other_columns) values (37,'Kelowna',181380,'e'); insert into cities (objectid,population_centre,population_2021,other_columns) values (40,'Kitchener',522888,'f'); insert into cities (objectid,population_centre,population_2021,other_columns) values (45,'London',423369,'g'); insert into cities (objectid,population_centre,population_2021,other_columns) values (51,'Montreal',3675219,'h'); insert into cities (objectid,population_centre,population_2021,other_columns) values (58,'Oshawa',335949,'i'); insert into cities (objectid,population_centre,population_2021,other_columns) values (59,'Ottawa–Gatineau',1068821,'j'); insert into cities (objectid,population_centre,population_2021,other_columns) values (65,'Quebec City',733156,'k'); insert into cities (objectid,population_centre,population_2021,other_columns) values (67,'Regina',224996,'l'); insert into cities (objectid,population_centre,population_2021,other_columns) values (76,'Saskatoon',264637,'m'); insert into cities (objectid,population_centre,population_2021,other_columns) values (82,'St. Catharines – Niagara Falls',242460,'n'); insert into cities (objectid,population_centre,population_2021,other_columns) values (83,'St. John''s',185565,'o'); insert into cities (objectid,population_centre,population_2021,other_columns) values (90,'Toronto',5647656,'p'); insert into cities (objectid,population_centre,population_2021,other_columns) values (92,'Vancouver',2426160,'q'); insert into cities (objectid,population_centre,population_2021,other_columns) values (94,'Victoria',363222,'r'); insert into cities (objectid,population_centre,population_2021,other_columns) values (98,'Windsor',306519,'s'); insert into cities (objectid,population_centre,population_2021,other_columns) values (99,'Winnipeg',758515,'t');
查询全表结果:
| OBJECTID | POPULATION_CENTRE | POPULATION_2021 | OTHER_COLUMNS |
|---|---|---|---|
| 11 | Calgary | 1305550 | a |
| 23 | Edmonton | 1151635 | b |
| 31 | Halifax | 348634 | c |
| 32 | Hamilton | 729560 | d |
| 37 | Kelowna | 181380 | e |
| 40 | Kitchener | 522888 | f |
| 45 | London | 423369 | g |
| 51 | Montreal | 3675219 | h |
| 58 | Oshawa | 335949 | i |
| 59 | Ottawa–Gatineau | 1068821 | j |
| 65 | Quebec City | 733156 | k |
| 67 | Regina | 224996 | l |
| 76 | Saskatoon | 264637 | m |
| 82 | St. Catharines – Niagara Falls | 242460 | n |
| 83 | St. John's | 185565 | o |
| 90 | Toronto | 5647656 | p |
| 92 | Vancouver | 2426160 | q |
| 94 | Victoria | 363222 | r |
| 98 | Windsor | 306519 | s |
| 99 | Winnipeg | 758515 | t |
问题
我需要在GIS软件的WHERE子句窗口中编写SQL表达式,筛选出人口排名前4的城市。但受限于File Geodatabase的SQL功能,是否有可行的实现方式?另外,好奇在早期SQL数据库(比如刚发布的SQLite)功能有限的情况下,这类Top-N查询是怎么实现的?
解答
针对File Geodatabase的解决方案
根据列出的SQL支持限制,确实无法直接通过纯SQL筛选出前4的城市。因为缺少窗口函数、TOP/LIMIT这类直接的Top-N语法,且不支持关联子查询——而关联子查询是早期实现Top-N的常用方法之一。
不过可以尝试两种间接方式:
- 借助GIS软件自身功能:多数GIS工具(如ArcGIS Pro)支持对查询结果排序后手动选取前4条,或通过图层"选择"功能按人口字段排序后直接选取顶部记录,无需完全依赖SQL。
- 导出后处理:将
CITIES表导出到支持完整SQL的数据库(如SQLite、PostgreSQL),执行Top-N查询后再导回File Geodatabase。
早期SQL数据库的Top-N实现方法
在没有窗口函数、LIMIT/TOP语法的年代,主要依赖自连接+聚合统计的方式实现Top-N,以下以CITIES表为例,筛选前4人口城市:
SELECT c1.* FROM cities c1 JOIN cities c2 ON c1.population_2021 <= c2.population_2021 GROUP BY c1.objectid, c1.population_centre, c1.population_2021, c1.other_columns HAVING COUNT(DISTINCT c2.population_2021) <= 4 ORDER BY c1.population_2021 DESC;
原理是:对每一行记录,统计有多少条不同的记录人口数大于等于它,若这个数量≤4,说明它属于前4的范围(注意存在并列人口时,结果可能包含更多行,需根据需求调整)。
早期SQLite刚发布时(1.x版本)没有LIMIT语法,就是用类似的自连接聚合方法,或者依赖应用层读取所有结果后截断前N条。直到SQLite 2.0引入LIMIT语法,才简化了Top-N查询。
内容的提问来源于stack exchange,提问作者User1974
相关产品推荐
相关产品推荐

