Postgres仅排序字母数字

时间:2016-02-10 21:08:46

标签: ruby-on-rails postgresql

尝试在某些播客标题上对降序A-> Z进行排序,我只想要A-Z和0-9,其他一切都应该是最后一个:

.order('title ASC')  

在开始和结束时给我奇怪的结果。中间的大部分结果都很好:

> ["\"Success Living\" - Dr. Leigh-Davis",
  "\"The Real Deal\" with Dr. Leigh-Davis",
  "#WeThePeople_Live",
  "Alley Oop podcast",
  "Always Listening: Podcast Reviews",
  ... ### everything here is fine ### ...
  "Your Mom's House",
  "Zen Dude Fitness",
  "podCast411",
  "talk2Cleo"]

(前三个,后两个是奇怪的。)

2 个答案:

答案 0 :(得分:2)

用这个较长的参数替换.order('title ASC')

.order("
    CASE WHEN lower(title) BETWEEN 'a' AND 'zzzzz'
              OR title BETWEEN '0' AND '99999'       
         THEN lower(title)
         ELSE concat('zzzzz', lower(title))
    END")

这将不区分大小写(lower);当值以数字或字母开头时,它们会正常排序,而所有其他值将按照' zzzzz'作为前缀进行排序,从而强制它们到排序顺序的末尾。

SQL Fiddle

中的演示

使用正则表达式

此解决方案将上述想法与PJSCopeland(使用正则表达式)的想法相结合。同样,以非字母数字字符开头的字符串将以以字母数字字符开头的字符串排序:

.order("regexp_replace(lower(title), '([^[:alnum:] ])', 'zzz\1', 'gi')")

\1反向引用匹配的非字母数字字符,因此所有字符都以zzz为前缀。

SQL Fiddle

中的演示

答案 1 :(得分:0)

免责声明:我还没有对此进行过测试。它来自the documentation for Postgres 9.1

我有一个不精确的解决方案 - 不同之处在于标点符号将被忽略,您的条目最终会像这样:

.order("regexp_replace(title, '\W', '', 'gi')") # ASC is optional

=> ["Alley Oop podcast",
  "Always Listening: Podcast Reviews",
  "podCast411",
  "\"Success Living\" - Dr. Leigh-Davis",
  "talk2Cleo"
  "\"The Real Deal\" with Dr. Leigh-Davis",
  "Your Mom's House",
  "#WeThePeople_Live",
  "Zen Dude Fitness"]
  • regexp_replace是Postgres等效的Ruby [g]sub
  • \W表示任何非单词字符'并且将匹配除A-Z,a-z,0-9和_之外的任何其他内容。
    • 如果您也想忽略下划线,请将\W更改为[\W_]
  • ''是用以下内容替换匹配项:空字符串。
  • g标志表示所有匹配',i标志表示“不区分大小写”' (不需要lower())。