postgresql 如何在Postgres中获得最高字母数字值

r7knjye2  于 2023-02-15  发布在  PostgreSQL
关注(0)|答案(2)|浏览(130)

我有下面的库存股票代码表,并希望获取最高的字母数字值 * AR-JS-20 *。当我说"最高"时,我的意思是首先排序字母顺序,然后考虑数字,因此 * AR-JS-20 * 高于 * AL-JS-20 *。
顺便说一句,我不想把任何东西分成几个部分,因为它是未知的符号供应商将发送我在未来。我只是想一个字母数字排序像你排序计算机目录的名称。其中破折号,下划线,星号等来第一,然后数字,字母最后与级联优先级的第一个字符在符号中有最大的权重,然后第二个字符等等。
注:此问题已编辑,因此下面的一些答案不再适用。

AL-JS-20
AR-JS-20
AR-JS-9
AB-JS-8
AA-JS-1
1A-LM-30
2BA2-1
45HT

因此,理想情况下,如果按照我的要求对该表进行排序,它将如下所示

AR-JS-20
AR-JS-9
AB-JS-8
AL-JS-20
AA-JS-1
45HT
2BA2-1
1A-LM-30

但是,当我使用这个查询时:

select max(symbol) from stock

我得到:
一个三个三个一个
我也试过:

select max(symbol::bytea) from stock

但这会触发错误:
函数max(bytea)不存在

pobjuy32

pobjuy321#

这组问题有专门的标签:natural-sort(我现在添加了它。)
理想情况下,字符串部分和数值部分存储在单独的列中。
当你被那些不幸的符号困住的时候...
如果您的符号像示例所建议的那样规则,那么普通的left()split_part()就可以完成这项工作:

SELECT symbol
FROM   stock
ORDER  BY left(symbol, 5) DESC NULLS LAST
        , split_part(symbol, '-', 3)::int DESC NULLS LAST
LIMIT  1;
    • 或**,如果至少三个破折号是给定的:
...
ORDER  BY split_part(symbol, '-', 1) DESC NULLS LAST
        , split_part(symbol, '-', 2) DESC NULLS LAST
        , split_part(symbol, '-', 3)::int DESC NULLS LAST
LIMIT  1

参见:

  • 将逗号分隔的列数据拆分为其他列
    • 或**,如果格式不太严格:正则表达式函数用途更广,但开销也更大:
...
ORDER  BY substring(symbol, '^\D+') DESC NULLS LAST
        , substring(symbol, '\d+$')::int DESC NULLS LAST
LIMIT  1;

^ ...定位到字符串的开头
$ ...定位到字符串的末尾
\D ...非数字的类速记
\d ...数字的类速记
只取(尾部)数字,我们可以安全地转换为integer(假设数字〈2^31),并相应地排序。
如果可能缺少任何部件,则添加NULLS LAST,或者列可能为NULL

rekjcdws

rekjcdws2#

指定一个自定义order by,它将修剪最后一个-之前的所有内容,并将剩余的数字转换为int,然后取第一个:

select stock_code
from mytable
order by regexp_replace(stock_code, '-?[0-9]+-?', ''), regexp_replace(stock_code, '[^0-9-]', '')::int
limit 1

参见live demo
这适用于代码开头和结尾的数字:

  • regexp_replace(stock_code, '-?[0-9]+-?', '') "删除"数字和任何相邻的破折号
  • regexp_replace(stock_code, '[^0-9]', '') "删除"所有非数字

相关问题