如何在PostgreSQL中以正确的顺序返回记录

时间:2012-12-15 19:03:38

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

查询

select 'T' union all select 'Z'  order by 1

返回

Z
T

但正确的顺序应为

T
Z

尝试了3种不同的操作系统

  • Windows 2003服务器“PostgreSQL 9.1.3,由Visual C ++ build 1500,32位编译”
  • Windows 7“PostgreSQL 9.2.1,由Visual C ++ build 1600,32位编译”
  • Debian“在x86_64-unknown-linux-gnu上的PostgreSQL 9.1.2,由gcc-4.4 .real编译(Debian 4.4.5-8)4.4.5,64位”

数据库设置为:

Collation:      et_EE.UTF-8 
Character type: et_EE.UTF-8

如何解决这个问题?

更新

使用

创建数据库
CREATE DATABASE mydb WITH TEMPLATE=template0 OWNER=mydb_owner ENCODING='UNICODE'

OS语言环境在所有情况下都是爱沙尼亚语,因此数据库是在爱沙尼亚语语言环境中创建的。

select 'Z' collate "et_EE" union all select 'S' collate "et_EE" order by 1

返回正确的顺序:

S
Z

select 'Z' collate "et_EE" union all select 'T' collate "et_EE" order by 1

如答案中所述,返回无效顺序:

Z
T

3 个答案:

答案 0 :(得分:3)

原始SQL没有任何问题。

由于您使用爱沙尼亚语区域设置似乎没有按预期方式运行的原因,但Estonian collation rules要求'Z'在'T'之前。

您可以使用不同的排序规则或在en_US.UTF-8语言环境中创建数据库。

答案 1 :(得分:2)

查询没有错误。

UNION [ALL](或INTERSECTEXCEPT)查询被视为一个查询。 ORDER BY适用于所有腿的结合,而不仅仅是最后一条腿。您必须使用括号将ORDER BY本地化为查询的一个分支。引用手册here

  

select_statement UNION [ ALL | DISTINCT ] select_statement

     

select_statement 是没有SELECTORDER BY的任何LIMIT声明,   FOR UPDATEFOR SHARE条款。 (ORDER BYLIMIT可以附加   如果括在括号中,则表示子表达式。没有   括号中,这些条款将被视为适用于结果   UNION,而不是右手输入表达式。)

这只是有用的(a之前排序b):

SELECT 'b'
UNION ALL
SELECT 'a'
ORDER BY 1

与问题中的原始查询一样:

SELECT 'T' 
UNION ALL
SELECT 'Z'
ORDER BY 1

检查整理:

SHOW lc_collate;

et_EE.UTF-8是爱沙尼亚语区域设置,Z位于Estonian alphabet T之前。就是这样。

整理没有错误。

答案 2 :(得分:-1)

问题在于整理:

select 'T' collate "et_EE.utf8" a union all select 'Z' collate "et_EE.utf8" order by 1;
 a 
---
 Z
 T

使用en_US归类时,它可以正常工作:

select 'T' collate "en_US.utf8" a union all select 'Z' collate "en_US.utf8" order by 1;
 a 
---
 T
 Z