2

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

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

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
4

2 回答 2

4

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;
于 2012-10-16T14:00:32.227 回答
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
于 2012-10-19T08:57:12.520 回答