将串联与 ORDER BY 相结合
Posted
技术标签:
【中文标题】将串联与 ORDER BY 相结合【英文标题】:Combining concatenation with ORDER BY 【发布时间】:2013-09-13 10:24:34 【问题描述】:我在 Postgre (9.1.9) 中将串联与 order by 结合起来遇到了麻烦。 假设,我有一个包含 3 个字段的表格边框:
Table "borders"
Column | Type | Modifiers
---------------+----------------------+-----------
country1 | character varying(4) | not null
country2 | character varying(4) | not null
length | numeric |
前两个字段是国家代码,第三个字段是这些国家之间的边界长度。 主键在前两个字段中定义。
我需要选择一个对整个表具有唯一值的列,此外,该列应按降序选择。 为此,我将关键字段与分隔符连接起来,否则两个不同的行可能会给出相同的结果,例如 (AB, C 和 A, BC)。
所以我运行以下查询:
select country1||'_'||country2 from borders order by 1;
但是,在结果中,我看到排序中省略了“_”字符。 结果如下所示:
?column?
----------
A_CH
A_CZ
A_D
AFG_IR
AFG_PK
AFG_TAD
AFG_TJ
AFG_TM
AFG_UZB
A_FL
A_H
A_I
.
.
您可以看到结果被排序,好像字符串中不存在'_'。
如果我使用字母(比如“x”)作为分隔符 - 顺序是正确的。但是我必须使用一些没有出现在 country1 和 country2 字段中的特殊字符,以避免争用。
我应该怎么做,以便在排序过程中考虑到“_”字符。
编辑
原来串联与问题无关。问题是 order by 只是忽略了 '_' 字符。
【问题讨论】:
_
字符可能与排序相关,depending on your collation settings.
谢谢,这是我不知道的,从这里的答案中学到的。
【参考方案1】:
当您执行以下操作时会发生什么?
select country1||'_'||country2 from borders order by country1||'_'||country2
我对按 1 排序的知识只进行序数排序。它不会对连接的列执行任何操作。当然,我说的是 SQL Server 知识,所以如果我离题了,请告诉我。
已编辑:好的;当我发布我的帖子时,刚刚看到了帕拉多的帖子。也许您可以从此查询创建一个视图(给它一个列名),然后重新查询该视图,按该列排序?或执行以下操作:
select country_group from (
select country1||'_'||country2 as country_group from borders
) a
order by country_group
【讨论】:
我更新了一个问题,如果我使用字母作为分隔符,则顺序是正确的,所以问题不在1
的顺序中
Jutky,很公平。尝试上述编辑过的建议,然后按您喜欢的方式订购。似乎@Roman 的回答也可以。【参考方案2】:
只需按两列排序:
SELECT country1||'_'||country2 FROM borders ORDER BY country1, country2;
除非您使用聚合或窗口,否则 PostgreSQL 允许按列排序,即使您没有将它们包含在 SELECT 列表中。
正如另一个答案中所建议的,您还可以更改组合列的排序规则,但如果可以的话,对普通列进行排序会更快,特别是如果您对它们有索引。
【讨论】:
恐怕这不会涵盖所有情况。我会进一步检查。感谢您的简单建议。 查询正确,会“一网打尽”。更大的问题是为什么 PostgreSql 会这样。 这行不通。例如,您有两行(“A B”、“C”)和(“A”、“B”)。在您的解决方案中,第二行将在第一行之前。但实际上,字符串“A_B”应该在“A B_C”之后。 ping @RobertCo. @RobertCoThe bigger question is why is PostgreSql behaving that way.
这也让我很困扰。
@jutky “那样做”是什么意思?排序顺序由排序规则定义,因此行的顺序应仅取决于它。【参考方案3】:
select country1 || '_' || country2 collate "C" as a
from borders
order by 1
sql fiddle demo
根据 cmets 中讨论的注释:
1.) COLLATE "C"
适用于ORDER BY
子句,只要它通过位置参数 或别名 引用SELECT
子句中的表达式。如果您重复ORDER BY
中的表达式,如果您想相应地影响排序顺序,还需要重复COLLATE
子句。
sql fiddle demo
2.) 在_
不影响排序顺序的排序规则中,使用fog's query 更有效,因为它利用了现有索引 (primary key is defined on the first two fields
)。
但是,如果_
有影响,则需要对组合表达式进行排序:
sql fiddle demo
查询性能(在 Postgres 9.2 中测试):sql fiddle demo
PostgreSQL Collation Support in the manual.
【讨论】:
好,现在考虑到特殊字符,但它在字母之后排序。为什么,'_'的ASCII码比字母的ASCII码少? 哦,我明白了,字符不是按ASCII码排序的。它们按区域设置排序,并且字母排在特殊字符之前。有没有办法按字符的 ASCII 码对字符串进行排序? @jutky 我认为更好的方法是使用雾解决方案 正如我对他的回答所评论的那样,它并没有涵盖所有情况。 好吧 OP 需要按 country1_country2 对行进行排序,而不是按 country1、country2 排序,正如他在 cmets 中所说的那样去雾化答案 - 例如你有两行(“AB”、“C” ) 和 ("A","B")。在您的解决方案中,第二行将在第一行之前。但实际上,字符串 "A_B" 应该在 "A B_C" 之后 - sqlfiddle.com/#!1/50f30/2以上是关于将串联与 ORDER BY 相结合的主要内容,如果未能解决你的问题,请参考以下文章
oracle SQL语句中结合order by子句使用rownum
Mysql 排序Order by与分页limit结合的数据异常问题