【问题标题】:Set Order By to ignore punctuation on a per-column basis设置 Order By 以忽略每列的标点符号
【发布时间】:2013-07-01 18:00:13
【问题描述】:

是否可以通过包含 [](),; 等字符的标题字段对 PostgreSQL 查询的结果进行排序,但忽略这些标点符号并仅按文本字符排序?

我已阅读有关更改数据库排序规则或语言环境的文章,但没有找到任何关于如何在现有数据库上按列执行此操作的明确说明。这甚至可能吗?

【问题讨论】:

    标签: postgresql sql-order-by postgresql-9.1 collation


    【解决方案1】:

    “归一化”进行排序

    可以ORDER BY 子句中使用regexp_replace()'[^a-zA-Z]' 模式,但它只能识别纯ASCII 字母。最好使用class shorthand '\W',它可以识别您的语言环境中的其他非ASCII字母,例如äüóèß等。 或者您可以即兴创作并“借助 unaccent() 函数将所有带有变音符号元素的字符标准化为它们的基本形式。考虑这个小演示:

    SELECT *
          , regexp_replace(x, '[^a-zA-Z]', '', 'g')
          , regexp_replace(x, '\W', '', 'g')
          , regexp_replace(unaccent(x), '\W', '', 'g')
    FROM  (
    SELECT 'XY ÖÜÄöüäĆČćč€ĞğīїıŁłŃńŇňŐőōŘřŠšŞşůŽžż‘´’„“”­–—[](),;.:̈� XY'::text AS x) t
    

    ->SQLfiddle for Postgres 9.2.
    ->SQLfiddle for Postgres 9.1.

    正则表达式代码已在 9.2 版本中更新。我假设这是在 9.2 中改进处理的原因,其中示例中的所有字母字符都匹配,而 9.1 只匹配一些。

    unaccent() 由附加模块unaccent 提供。运行:

    CREATE EXTENSION unaccent;
    

    每个数据库使用一次(Postgres 9.1+,旧版本使用different technique)。

    语言环境/排序规则

    您必须知道 Postgres 依赖于底层操作系统的语言环境(包括排序规则)。排序顺序由您选择的区域设置或更具体的LC_COLLATE 控制。更多相关答案:
    String sort order (LC_COLLATE and LC_CTYPE)

    plans to incorporate collation support into Postgres directly,但目前不可用。

    许多语言环境忽略了您描述的用于对字符数据进行开箱即用排序的特殊字符。如果您的系统中安装了提供所需排序顺序的语言环境,则可以在 Postgres 9.1 或更高版本中临时使用它:

    SELECT foo FROM bar ORDER BY foo COLLATE "xy_XY"
    

    要查看当前 Postgres 安装中已安装和可用的排序规则:

    SELECT * FROM pg_collation;
    

    不幸的是,除非您破解源代码,否则无法定义您自己的自定义排序规则。

    排序规则通常受某个国家/地区使用的语言规则的约束。如果还有电话簿的话,电话簿的排序顺序会在里面……你的操作系统提供了它们。

    例如,在 Debian Linux 中,您可以使用:

    locale -a
    

    显示所有生成的语言环境。并且:

    dpkg-reconfigure locales
    

    作为 root 用户(多种方式之一)生成/安装更多。

    【讨论】:

    • 这都是很好的信息,但我读过各种文章说有不同的排序规则(尽管这是我第一次看到将一个排序规则应用于查询是多么容易),但是如何我是否知道在查询中使用哪种排序规则以获得所需的结果?排序规则支持文章没有提供排序规则列表以及每个排序规则下的排序方式。
    • @tufelkinder:我在回答中添加了更多内容。
    • 我很感激。该查询确实提供了可用语言环境的列表,但这并不能帮助我确定哪个语言环境将产生哪种类型的排序,除非我遗漏了什么?
    • @tufelkinder:排序规则很复杂,很难用简短的评论来描述。每个国家/语言组合都有自己的一套规则。您通常会在一套国家语法规则中找到它们。
    【解决方案2】:

    如果您想在一个特定查询中进行此排序,您可以

    ORDER BY regexp_replace(title, '[^a-zA-Z]', '', 'g')
    

    它将从字符串中删除所有非A-Z,并按结果字段排序。

    【讨论】:

    • 这真的很有帮助,而且肯定会让我的结果朝着正确的方向发展。现在在 Django 中实现它...
    猜你喜欢
    • 1970-01-01
    • 2011-08-06
    • 2010-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多