【问题标题】:How to do sorting on irregular Alphanumeric data in postgres sql如何在postgres sql中对不规则的字母数字数据进行排序
【发布时间】:2012-10-16 13:50:06
【问题描述】:

对于示例表的特定列符号,我有以下示例数据。

(更新:)数据不是常规模式。数字可以出现在字符之间的任何位置。

symbol

COL4A1
COL4A3
COL8A2
COL2A1
COL12A1
COL12A1
COL16A1
COL19A1

我需要在数据库级别对这些数据进行排序。我使用了以下查询:

select symbol from sample order by symbol asc

结果如下:

COL12A1
COL12A1
COL16A1
COL19A1
COL2A1
COL4A1
COL4A3
COL8A2

但我需要通过以下方式获取订单:

COL2A1
COL4A1
COL4A3
COL8A2
COL12A1
COL12A1
COL16A1
COL19A1

【问题讨论】:

  • 我看到您的编辑改变了您问题的含义。如果您大幅更改问题的参数,请考虑提出一个新问题。此外,当您编辑问题时,不会发送任何通知,因此没有人知道您已将其更改为不同的问题。
  • 我已经发布了您的问题的后续内容,描述了新问题,其中包含适当可变的示例数据、SQLFiddle 等。请查看它是否准确地描述了您的问题:@ 987654321@
  • @Craig Ringer,我从我的一位队友那里得到了解决方案。它解决了我的问题。请参阅以下答案。

标签: postgresql natural-sort


【解决方案1】:

PostgreSQL 不提供可以执行“人性化”排序的数字感知排序规则,例如“1A、2A、3A、... 10A、11A、...”。它依赖于操作系统进行排序,我不知道有任何操作系统会向应用程序公开这种排序规则。

为此,您需要根据模式拆分文本并按模式部分的顺序,可能使用regexp_matches

CREATE TABLE Table1 ("symbol" text);
INSERT INTO Table1 ("symbol") VALUES
    ('COL4A1'),('COL4A3'),('COL8A2'),('COL2A1'),
    ('COL12A1'),('COL12A1'),('COL16A1'),('COL19A1');

WITH matched(symbol, symbol_parts) AS (
  SELECT symbol, regexp_matches(symbol, '(\D*)(\d+)(\D+)(\d+)')
  FROM Table1
)
SELECT symbol 
FROM matched
ORDER BY symbol_parts[1], symbol_parts[2]::integer,
         symbol_parts[3], symbol_parts[4]::integer;

【讨论】:

  • 如果你经常这样做,那么预先计算和存储这些部分(或将它们转换为可排序的东西,例如 INSERT/UPDATE 上的COL002A001)可能是个好主意。
  • @SivaramChintalapudi 仅供参考,我已经更正了正则表达式以处理首先包含数字的代码并更正确地匹配非数字。
【解决方案2】:
CREATE OR REPLACE FUNCTION pad_numbers(text)
              RETURNS text AS
            $BODY$
                SELECT regexp_replace(
                regexp_replace(
                  regexp_replace(
                    regexp_replace(
                      $1, 
                      E'(^|\\D)(\\d{1,3}($|\\D))', E'\\1000\\2', 'g'
                    ), E'(^|\\D)(\\d{4,6}($|\\D))', E'\\1000\\2', 'g'
                  ), E'(^|\\D)(\\d{7}($|\\D))', E'\\100\\2', 'g'
                ), E'(^|\\D)(\\d{8}($|\\D))', E'\\10\\2', 'g'
              );
            $BODY$
              LANGUAGE 'sql' VOLATILE;


select symbol from sample order by pad_numbers(symbol) asc

【讨论】:

  • 它可以处理字符之间最多9位的数字
  • 我可能更喜欢这里给出的一种方法 (stackoverflow.com/questions/12965463/…),但最终当然取决于你。
  • @Craig Ringer:是的。你是对的。我认为它们是非常有效的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-08-18
  • 2011-02-06
  • 2019-02-17
  • 1970-01-01
  • 2018-07-29
  • 1970-01-01
  • 2011-07-25
相关资源
最近更新 更多