【问题标题】:Natural sort supporting big numbers支持大数的自然排序
【发布时间】:2019-12-12 14:11:08
【问题描述】:

我有一些这样的数据:

 id | templateName 
----+--------------
 10 | a
 61 | a
 63 | a
  4 | a
  6 | a
  7 | a
 34 | a
 35 | a
 62 | a
  1 | a
 13 | a
 25 | a
 26 | a
 66 | a
 68 | a
 70 | a
 65 | a
  5 | a1
 73 | a5
  3 | a15
  2 | a15a
 69 | a15b
 64 | a15b4
 74 | a15b21
  8 | a214748364

我正在使用以下代码进行自然排序:

CREATE TYPE ai AS (a text, i int);

select id, "templateName" from daily_templates
order by ARRAY(SELECT ROW(x[1], CASE x[2] WHEN '' THEN '0' ELSE x[2] END)::ai
               FROM regexp_matches("templateName", '(\D*)(\d*)', 'g')  x)
       , "templateName";

而且效果很好,就像我在上面展示的那样。现在我想支持大数,例如

a111111111111111111111

这将超出integer 的范围。我怎样才能做到这一点? 参考:Humanized or natural number sorting of mixed word-and-number strings

【问题讨论】:

  • 如果您的数字不是任意大的,您可以在ai 中使用BIGINT(= 8 字节整数)代替INT for i。对于非常大的数字DECIMAL可能是一个解决方案。
  • 我试图创建 i bigint,但它仍然转换为整数,我认为是因为 regexp_matches

标签: sql postgresql natural-sort


【解决方案1】:

它像@clemens 建议的那样工作。在复合类型中使用numeric (= decimal):

CREATE TYPE ai AS (a text, i numeric);

db小提琴here

我在参考答案中使用int 的原因是性能。

【讨论】:

    【解决方案2】:

    或者,如果您拥有支持 ICU 排序规则的 PostgreSQL v10 或更高版本,则可以

    CREATE COLLATION natural (provider = icu, locale = 'en-US-u-kn-true');
    

    然后像这样排序:

    ... ORDER BY "templateName" COLLATE natural
    

    【讨论】:

    • 嗨,我遇到了一个问题,它与排序的性能有关。有什么可以改进的吗?
    • 这可能无济于事。排序规则越复杂,排序的开销就越大。
    猜你喜欢
    • 2010-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多