Postgres:按字符串的一部分订购数据

时间:2012-01-24 15:08:00

标签: sql postgresql

我有一个列名,代表一个人的姓名,格式如下:

firstname [middlename] lastname [, Sr.|Jr.]

例如:

John Smith
John J. Smith
John J. Smith, Sr.

如何按姓氏订购商品?

3 个答案:

答案 0 :(得分:10)

正确,更快的版本可能如下所示:

SELECT *
FROM   tbl
ORDER  BY substring(name, '([^[:space:]]+)(?:,|$)')

或者:

ORDER  BY substring(name, E'([^\\s]+)(?:,|$)')

甚至:

ORDER  BY substring(name, E'([^\\s]+)(,|$)')

解释

[^[:space:]]+ ..由一个或多个非空白字符组成的第一个(也是最长的)字符串 (,|$) ..以逗号或字符串结尾终止。

最后两个示例使用了转义字符串语法和class-shorthand \s而不是长格式[[:space:]](在字符类中丢失了括号的外层)。

我们实际上不必在我们想要提取的部分之后使用非捕获括号(?:) ,因为(quoting the manual):

  

..如果模式包含任何括号,则该部分文本为   匹配第一个带括号的子表达式(左边的那个)   先括号括起来。)

测试

SELECT substring(name, '([^[:space:]]+)(?:,|$)')
FROM  (VALUES 
  ('John Smith')
 ,('John J. Smith')
 ,('John J. Smith, Sr.')
 ,('foo bar Smith, Jr.')
) x(name)

答案 1 :(得分:2)

您应该为此目的使用功能索引 http://www.postgresql.org/docs/7.3/static/indexes-functional.html

以某种方式在你的情况下......

CREATE INDEX test1_lastname_col1_idx ON test1 (split_part(col1, ' ', 3));
SELECT * FROM test1 ORDER BY split_part(col1, ' ', 3);

答案 2 :(得分:2)

SELECT *
FROM t
ORDER BY substring(name, E'^.*\\s([^\\s]+)(?=,|$)') ASC

虽然这应该提供您正在寻找的排序,但将名称存储在多个列中并根据您需要排序的名称部分对其进行索引会更便宜。