Oracle 11g:如何为每个城镇返回单条记录
按城镇分组返回任意一条完整地址记录的解决方案
针对你的ADDRESS_TABLE(30万条记录,仅约100个唯一城镇),以下几种SQL方案可以帮你为每个城镇提取任意一条完整记录:
方案1:窗口函数(通用高效,支持PostgreSQL、SQL Server、MySQL 8.0+)
窗口函数是最推荐的方式,逻辑清晰且性能优异,适合大数据量场景:
SELECT * FROM ( SELECT *, -- 按城镇分组,每组内按UNIQUE_ID排序(可替换为其他字段,比如RAND()实现随机) ROW_NUMBER() OVER (PARTITION BY 城镇名字段 ORDER BY UNIQUE_ID) AS row_num FROM ADDRESS_TABLE ) grouped_addr WHERE row_num = 1;
PARTITION BY 城镇名字段:将数据按城镇名拆分分组ROW_NUMBER():为每组内的记录分配序号- 筛选
row_num = 1即可得到每个城镇的第一条记录(任意一条,取决于排序规则)
方案2:GROUP BY + 聚合函数(兼容多数数据库)
如果你的数据库不支持窗口函数,可通过聚合函数提取组内任意字段值:
SELECT 城镇名字段, MAX(UNIQUE_ID) AS UNIQUE_ID, MAX(STREET_NUMBER) AS STREET_NUMBER, -- 其他字段依次用MAX/MIN包裹,取组内任意非空值 MAX(其他字段名) AS 其他字段名 FROM ADDRESS_TABLE GROUP BY 城镇名字段;
注意:MAX/MIN只是用来获取组内任意一个有效数值,你不需要关心具体取到的是哪条记录的字段值。
方案3:MySQL 5.x专属方案(无窗口函数时使用)
若使用MySQL 5.x版本,可结合DISTINCT和JOIN实现:
SELECT addr.* FROM (SELECT DISTINCT 城镇名字段 FROM ADDRESS_TABLE) unique_towns JOIN ADDRESS_TABLE addr ON addr.城镇名字段 = unique_towns.城镇名字段 GROUP BY unique_towns.城镇名字段;
解释:先获取所有唯一城镇列表,再关联原表,GROUP BY后MySQL会自动返回每组的第一条匹配记录(需确保未开启ONLY_FULL_GROUP_BY sql模式)。
额外提示
- 由于唯一城镇仅约100个,三种方案的性能都不会有问题,30万条数据处理耗时极短。
- 若需要随机返回每个城镇的记录,可将窗口函数中的
ORDER BY UNIQUE_ID替换为ORDER BY RAND(),性能影响可忽略。
内容的提问来源于stack exchange,提问作者pleaseandthankyou
相关产品推荐
相关产品推荐

