PostgreSQL 查询字母数字字符串的排序顺序不正确

问题描述 投票:0回答:1

我正在尝试使用以下 PostgreSQL 查询对表门中的列标题进行排序:

SELECT title
FROM door
ORDER BY
  CASE 
    WHEN title ~ '^\d+' THEN CAST(regexp_replace(title, '[^0-9]', '', 'g') AS INTEGER)
    ELSE NULL
  END ASC,
  CASE 
    WHEN title ~ '^\d+' THEN regexp_replace(title, '\d+', '', 'g')
    ELSE title
  END ASC;

查询当前产生以下结果:

"DR-1"
"DR-01"
"DR-02"
"DR-03"
"DR-04"
"DR-100"
"DR-1001"
"DR-101"
"DR-102"
"DR-104"
"Entrance-1"
"Entrance-2"
"MY-Prefix-10-Entrance-1"
"MY-Prefix-11-Entrance-1"
"MY-Prefix-19-Entrance-1"
"MY-Prefix-1-Entrance-1"
"MY-Prefix-20-Entrance-1"
"MY-Prefix-2-Entrance-1"
"MY-Prefix-3-Entrance-1"
"MY-Prefix-8-Entrance-1"
"MY-Prefix-9-Entrance-1"
"MY-Prefix-9-Entrance-2"
"MY-Prefix-9-Entrance-3"

然而,我期待的结果是:

"DR-1"
"DR-01"
"DR-02"
"DR-03"
"DR-04"
"DR-100"
"DR-101"
"DR-102"
"DR-104"
"DR-1001"
"Entrance-1"
"Entrance-2"
"MY-Prefix-1-Entrance-1"
"MY-Prefix-2-Entrance-1"
"MY-Prefix-3-Entrance-1"
"MY-Prefix-8-Entrance-1"
"MY-Prefix-9-Entrance-1"
"MY-Prefix-9-Entrance-2"
"MY-Prefix-9-Entrance-3"
"MY-Prefix-10-Entrance-1"
"MY-Prefix-11-Entrance-1"
"MY-Prefix-19-Entrance-1"
"MY-Prefix-20-Entrance-1"

查询未正确对标题列包含混合前缀和数字段的行进行排序,特别是具有 MY-Prefix 模式的条目。我怀疑这是由于 ORDER BY 子句中的逻辑未正确处理多段字母数字字符串的排序所致。

我想要:

对从

title
中提取数字段并按数字排序的行进行排序。 正确处理字母数字前缀,以便像
MY-Prefix-1-Entrance-1
这样的条目出现在
MY-Prefix-10-Entrance-1
之前。

postgresql natural-sort
1个回答
0
投票

对于示例数据模式,您可以将要排序的列拆分为两列,其中第一列新列仅包含非数字字符,第二列仅包含数字字符,并按如下方式排序。

dbfiddle

with door as (
    select title from ( 
       values ('DR-1'), ('DR-01'), ('DR-02'), ('DR-03'), ('DR-04'), ('DR-100'), ('DR-1001'), ('DR-101'), ('DR-102'), ('DR-104'), ('Entrance-1'), ('Entrance-2'), ('MY-Prefix-10-Entrance-1'), ('MY-Prefix-11-Entrance-1'), ('MY-Prefix-19-Entrance-1'), ('MY-Prefix-1-Entrance-1'), ('MY-Prefix-20-Entrance-1'), ('MY-Prefix-2-Entrance-1'), ('MY-Prefix-3-Entrance-1'), ('MY-Prefix-8-Entrance-1'), ('MY-Prefix-9-Entrance-1'), ('MY-Prefix-9-Entrance-2'), ('MY-Prefix-9-Entrance-3')
    ) as ta (title)
)

select title
    -- , REGEXP_REPLACE(title, '[[:digit:]]+', '', 'g')::text as chars 
    -- , REGEXP_REPLACE(title, '[^[:digit:]]+', '', 'g')::integer as numbers
from door order by 
REGEXP_REPLACE(title, '[[:digit:]]+', '', 'g')::text,
REGEXP_REPLACE(title, '[^[:digit:]]+', '', 'g')::integer
© www.soinside.com 2019 - 2024. All rights reserved.