CREATE OR REPLACE TABLE `tmp` (
`ord` int(5) unsigned NOT NULL DEFAULT 10000,
`val` varchar(50) CHARACTER SET utf8 COLLATE utf8_estonian_ci NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `tmp` (`ord`, `val`)
VALUES (1,'foo'), (2,'baz'), (3,'baz'), (4,'foo');
现在考虑查询
-- 1) Example with ASC sorting
select group_concat( distinct val
ORDER BY ord ASC SEPARATOR ';') from tmp;
正如预期的那样,它会吐出foo;baz
问题是,为什么
-- 2) Example with DESC sorting
select group_concat( distinct val
ORDER BY ord DESC SEPARATOR ';') from tmp;
输出baz;foo
?
看起来Mysql是如何进行提升排序然后将其转换为DESC
我希望从(4,'foo'), (3,'baz')
返回结果。
数据库版本= 10.2.12-MariaDB-log
如果涉及更多数据,则更加引人注目:DBFiddle
INSERT INTO `tmp` (`ord`, `val`)
VALUES (1,'foo'), (2,'baz'), (3,'baz'), (4,'bar'), (5,'foo');
select group_concat( distinct val
ORDER BY ord ASC SEPARATOR ';') from tmp ;
- > foo;baz;bar
select group_concat( distinct val
ORDER BY ord DESC SEPARATOR ';') from tmp;
- > bar;baz;foo
??
我确实在这里预期foo;bar;baz
。
如果不需要DISTINCT,无论是ASC还是DESC,数据库都会按预期返回。
答案 0 :(得分:1)
看起来像你的第一个例子:
select group_concat( distinct val
ORDER BY ord ASC SEPARATOR ';') from tmp;
-- order
(1,'foo'), (2,'baz')
根据检索顺序1的行为是在2之前,所以你得到foo;bar
。
在我看来,你需要:
select group_concat( distinct val ORDER BY val ASC SEPARATOR ';') from tmp;
<强> DBFiddle Demo 强>
修改强>
这与以下情况相同:
CREATE TABLE tmp(ord int, val varchar(10)) ;
INSERT INTO tmp (ord, val) VALUES (1,'foo'), (2,'baz'), (3,'baz'), (4,'foo');
SELECT DISTINCT val
FROM tmp
ORDER BY ord;
<强> DBFiddle Demo2 强>
请注意,对于其他数据库,此查询将返回错误:
PostgreSQL:
ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list
LINE 3: ORDER BY ord;
SQL Server:
Msg 145 Level 15 State 1 Line 1
ORDER BY items must appear in the select list if SELECT DISTINCT is specified.
Oracle:
ORA-01791: not a SELECTed expression
MySQL when SET @@sql_mode = 'ONLY_FULL_GROUP_BY';
ORDER BY clause is not in SELECT list, references column 'ord'
which is not in SELECT list; this is incompatible with DISTINCT
更多信息:SELECT DISTINCT and ORDER BY in MySQL
基于What's New in SQL:2016的LISTAGG(DISTINCT ... )
:
listagg(distinct ...)
如果按汇总值排序:listagg(distinct X ,...)在组内(按 X 排序)
答案 1 :(得分:0)
在进行了一些调查后,结果非常简单,所有返回的结果 - 预期或意外 - 确实是正确的。
MySQL 5.7 Reference Manual中的神奇句子是
在选择值后发生结果集排序
所以
select group_concat( distinct val
ORDER BY ord XXSC SEPARATOR ';') from tmp;
首先执行作业的DISTINCT部分并将其作为中间结果:
-- unordered
(1,'foo'), (2,'baz')
现在引擎获取此结果并对其进行排序。 ASC或DESC按要求。