考虑这样的mysql架构:
CREATE TABLE `translations` (
group_id INT(11),
lang VARCHAR(2),
text VARCHAR(9),
UNIQUE INDEX `group_id_lang` (`group_id`, `lang`)
)
这里的内容应该非常明显 - 我有一个group_id的翻译。
现在,如果我要运行以下查询,要获取所有使用首选语言的群组' EN',请回退到' RU',如果这些翻译都不存在,那么回归任何可用的语言,一切都作为魅力
SELECT *
FROM (
SELECT *
FROM translations
ORDER BY lang = 'EN' DESC, lang = 'RU' DESC
) translations
GROUP BY group_id
+----------+------+---------+
| group_id | lang | text |
+----------+------+---------+
| 1 | EN | Estonia |
| 2 | EN | England |
| 3 | RU | Швеция |
+----------+------+---------+
如你所见,我会得到3排,最后一排倒回到RU' RU'因为' EN'没有出现在那个群体上。到目前为止一切都很好..
现在,如果我还想通过添加GROUP_CONCAT(lang) AS translations
选择所有可用语言作为列,那么事情会有点模糊:
SELECT *, GROUP_CONCAT(lang) AS available_translations
FROM (
SELECT *
FROM translations
ORDER BY lang = 'EN' DESC, lang = 'RU' DESC
) translations
GROUP BY group_id
+----------+------+-----------+--------------+
| group_id | lang | text | translations |
+----------+------+-----------+--------------+
| 1 | ET | Eesti | ET,EN,RU |
| 2 | ET | Inglismaa | ET,EN,RU |
| 3 | RU | Швеция | RU,ET |
+----------+------+-----------+--------------+
现在,mysql并不尊重我的ORDER BY
子句,并且按照原生顺序进行分组,因为根本没有排序。
为什么GROUP_CONCAT
会导致此问题?
如何使其能够使用首选语言以及按行列出可用的翻译?
另外,如果你想摆弄here you go
答案 0 :(得分:3)
在最外层查询之前不保证结果的顺序,因此即使您已经订购了子查询,这也不是读取记录的保证顺序,而是由外部查询返回。但主要的问题是,你是通过扩展来滥用MySQL Group,它允许你选择group by子句或聚合函数中没有包含的列。
为了简化您的查询,您需要:
SELECT group_id, text
FROM translations
GROUP BY group_id
ORDER BY lang = 'EN' DESC, lang = 'RU' DESC
除非text
在功能上依赖于group_id
,否则这会破坏sql标准,但是,MySQL允许它,但是,正如MySQL documents中所述
服务器可以自由选择每个组中的任何值,因此除非它们相同,否则所选的值是不确定的。此外,添加ORDER BY子句不会影响每个组中值的选择。
因此,即使您有一个订单,但在每个组选择了一行之后才会适用,并且这一行是不确定的。您所做的只是订购最终结果集。
为了解决这个问题并获得确定结果,您可以使用GROUP_CONCAT
将所有文本连接在一起,并明确说明您所需的顺序:
GROUP_CONCAT(text ORDER BY lang = 'EN' DESC, lang = 'RU' DESC)
然后使用SUBSTRING_INDEX
提取第一个词。所以你的查询变为:
SELECT Group_id,
SUBSTRING_INDEX(
GROUP_CONCAT(lang
ORDER BY lang = 'EN' DESC,
lang = 'RU' DESC),
',', 1) AS lang,
SUBSTRING_INDEX(
GROUP_CONCAT(text
ORDER BY lang = 'EN' DESC,
lang = 'RU' DESC),
',', 1) AS Text,
GROUP_CONCAT(lang ORDER BY lang = 'EN' DESC,
lang = 'RU' DESC) AS available_translations
FROM translations
GROUP BY Group_id;
<强> Example on SQL Fiddle 强>