SQL地址门牌排序,字典序转为数字序

页面有一批地址数据查询,结果字符排序默认是字典序的,所以造成了门牌3号在30号之前,影响用户体验;

csv 复制代码
id, road_code, road_name, address_fullname, address_name
102	10086	人民一路	北江省南海市西湖区人民一路3号	3号
103	10086	人民一路	北江省南海市西湖区人民一路11号	11号
109	10086	人民一路	北江省南海市西湖区人民一路27号	27号
116	10086	人民一路	北江省南海市西湖区人民一路7号	7号
108	10086	人民一路	北江省南海市西湖区人民一路30号	30号
114	122847	幸福大道	北江省幸福市中新区幸福大道7号	7号
sql 复制代码
SELECT id, road_code, road_name, address_fullname, address_name
FROM address
WHERE road_code = 10086 
ORDER BY address_name ASC

想到办法是提取名称的数字再排序。数据量大有两千多万条,不可能都跑一边提取排序,要么冗余一个字段存放提取的数字?

"如非必要,勿增实体"------奥卡姆剃刀原则

新加字段代码要改,治理维护也是问题。考虑到就这里功能用到了这个排序,而且道路代码是必传值,先被road_code值筛选过滤后,最后实际提取转换的数据并不多。

sql 复制代码
SELECT id, road_code, road_name, address_fullname, address_name
FROM address
WHERE road_code = 10086 
ORDER BY COALESCE(NULLIF(regexp_replace(address_name, '\D','','g'), ''), '0')::NUMERIC ASC

COALESCE(NULLIF(regexp_replace(address_name, '\D','','g'), ''), '0')::NUMERIC

正则全局匹配将地址中非数字替换成空字符,为了防止地址不存在或者没有数字的情况,

使用NULLIF()和COALESCE()兜底,统一置为'0',最后转为NUMERIC数字类型用作排序。

(空字符串 ''::NUMERIC 类型转换报异常)

注:
COALESCE(value [, ...])

返回第一个非空参数的值。当且仅当所有参数都为空时才会返回NULL空值。

NULLIF(value1, value2)

当value1和value2相等时,NULLIF返回NULL空值。 否则它返回value1。

另附,测试表和数据:

sql 复制代码
DROP TABLE IF EXISTS "public"."address";
CREATE TABLE "public"."address" (
  "id" int8 NOT NULL,
  "road_code" int8,
  "road_name" varchar(255) COLLATE "pg_catalog"."default",
  "address_fullname" varchar(255) COLLATE "pg_catalog"."default",
  "address_name" varchar(255) COLLATE "pg_catalog"."default"
);

COMMENT ON COLUMN "public"."address"."id" IS '主键';
COMMENT ON COLUMN "public"."address"."road_code" IS '道路编码';
COMMENT ON COLUMN "public"."address"."road_name" IS '道路名称';
COMMENT ON COLUMN "public"."address"."address_fullname" IS '地址全名';
COMMENT ON COLUMN "public"."address"."address_name" IS '地址名称';

INSERT INTO "public"."address" VALUES (102, 10086, '人民一路', '北江省南海市西湖区人民一路3号', '3号');
INSERT INTO "public"."address" VALUES (103, 10086, '人民一路', '北江省南海市西湖区人民一路11号', '11号');
INSERT INTO "public"."address" VALUES (109, 10086, '人民一路', '北江省南海市西湖区人民一路27号', '27号');
INSERT INTO "public"."address" VALUES (116, 10086, '人民一路', '北江省南海市西湖区人民一路7号', '7号');
INSERT INTO "public"."address" VALUES (108, 10086, '人民一路', '北江省南海市西湖区人民一路30号', '30号');
INSERT INTO "public"."address" VALUES (114, 122847, '幸福大道', '北江省幸福市中新区幸福大道7号', '7号');

ALTER TABLE "public"."address" ADD CONSTRAINT "address_pkey" PRIMARY KEY ("id");
相关推荐
junnhwan13 分钟前
【苍穹外卖笔记】Day04--套餐管理模块
java·数据库·spring boot·后端·苍穹外卖·crud
一枚正在学习的小白31 分钟前
PG数据文件位置迁移
linux·运维·服务器·数据库
真的想不出名儿1 小时前
上传头像到腾讯云对象存储-前端基于antdv
java·数据库·腾讯云
Dreams_l1 小时前
初识redis(分布式系统, redis的特性, 基本命令)
数据库·redis·缓存
数据库知识分享者小北1 小时前
Qoder + ADB Supabase :5分钟GET超火AI手办生图APP
数据库·后端
点亮一颗LED(从入门到放弃)2 小时前
SQLite3数据库——Linux应用
linux·数据库·sqlite
济南java开发,求内推2 小时前
mongodb一个服务器部署多个节点
服务器·数据库·mongodb
武子康3 小时前
Java-148 深入浅出 MongoDB 聚合操作:$match、$group、$project、$sort 全面解析 Pipeline 实例详解与性能优化
java·数据库·sql·mongodb·性能优化·系统架构·nosql
程序猿(雷霆之王)3 小时前
MySQL——复合查询
数据库·mysql
IT 小阿姨(数据库)3 小时前
PostgreSQL etcd 集群介绍
运维·数据库·sql·postgresql·centos·etcd