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");
相关推荐
云和恩墨16 小时前
OceanBase企业版会话级SQL跟踪实操:DBMS_MONITOR(类Oracle 10046事件)
数据库·sql·oracle·oceanbase
为什么不问问神奇的海螺呢丶16 小时前
oracle 数据库巡检 sql
数据库·sql·oracle
麦麦鸡腿堡16 小时前
MySQL数据库操作指令
数据库·mysql
陈天伟教授1 天前
人工智能训练师认证教程(2)Python os入门教程
前端·数据库·python
Elastic 中国社区官方博客1 天前
Elasticsearch:在分析过程中对数字进行标准化
大数据·数据库·elasticsearch·搜索引擎·全文检索
聪明努力的积极向上1 天前
【MYSQL】字符串拼接和参数化sql语句区别
数据库·sql·mysql
代码or搬砖1 天前
RBAC(权限认证)小例子
java·数据库·spring boot
神仙别闹1 天前
基于QT(C++)实现学本科教务系统(URP系统)
数据库·c++·qt
2301_768350231 天前
MySQL为什么选择InnoDB作为存储引擎
java·数据库·mysql
上海蓝色星球1 天前
迈向智慧电网新纪元:上海蓝色星球数字孪生变电主子站系统
运维·数据库