MySQL GROUP BY 丢失的子查询中的 ORDER BY
MySQL ORDER BY from subquery lost by GROUP BY
我有一个 table x :
id lang externalid
1 nl 10
2 nl 11
3 fr 10
从这个 table 我想要特定语言和 externalid 的所有行,如果该语言不存在 externalid,我想要任何其他语言的行。
子查询排序table正确,但是当我添加group by时,子查询的排序丢失了。这适用于较旧的 mysql 版本,但不适用于 5.7。
(
SELECT
*
FROM
x
ORDER BY FIELD(lang, "fr") DESC, id
)
as y
group by externalid
我希望查询 return ID 为 2 和 3 的记录。因此,对于每个不同的外部 ID,如果可能,lang = 'fr',否则任何其他 lang。
我该如何解决这个问题?
您的子查询生成一个结果集(一个虚拟 table)并传递给您的外部查询。
所有 SQL 查询无一例外地以 unpredictable order 生成其结果,除非您在 ORDER BY
中完全指定顺序条款。
Unpredictable 就像 random, 除了更糟。随机意味着每次 运行 查询时您都会得到不同的顺序。 Unpredictable 意味着您每次都会得到相同的订单,直到您不这样做为止。
MySQL 通常忽略子查询中的 ORDER BY
子句(有一些例外,主要与子查询 LIMIT
子句有关)。将您的 ORDER BY
移至顶级查询。
编辑。您还滥用了 MySQL 对 GROUP BY
臭名昭著的非标准扩展。
你说的是给定 externalid
和 land
。因此无需按 externalid
分组;仅使用 where
子句。
与 ORDER BY
和 LIMIT
相结合,您将获得所需的记录(即,如果存在这样的记录,则为所需的语言,否则为其他语言)。
select *
from mytable
where externalid = 10
order by lang = 'fr' desc
limit 1;
更新: 好的,根据您的评论,您希望每个 externalid
获得 "best" 条记录。在标准 SQL 中,您将为此使用 ROW_NUMBER
。其他 DBMS 有进一步的解决方案,例如Oracle 的 KEEP FIRST
或 Postgre 的 DISTINCT ON
。 MySQL 不支持其中任何一个。一种方法是用变量模拟 ROW_NUMBER
。另一种方法是将上述查询用作每个 externalid
的子查询以查找最佳记录:
select *
from mytable
where id in
(
select
(
select m.id
from mytable m
where m.externalid = e.externalid
order by m.lang = 'fr' desc
limit 1
) as best_id
from (select distinct externalid from mytable) e
);
我有一个 table x :
id lang externalid
1 nl 10
2 nl 11
3 fr 10
从这个 table 我想要特定语言和 externalid 的所有行,如果该语言不存在 externalid,我想要任何其他语言的行。
子查询排序table正确,但是当我添加group by时,子查询的排序丢失了。这适用于较旧的 mysql 版本,但不适用于 5.7。
(
SELECT
*
FROM
x
ORDER BY FIELD(lang, "fr") DESC, id
)
as y
group by externalid
我希望查询 return ID 为 2 和 3 的记录。因此,对于每个不同的外部 ID,如果可能,lang = 'fr',否则任何其他 lang。
我该如何解决这个问题?
您的子查询生成一个结果集(一个虚拟 table)并传递给您的外部查询。
所有 SQL 查询无一例外地以 unpredictable order 生成其结果,除非您在 ORDER BY
中完全指定顺序条款。
Unpredictable 就像 random, 除了更糟。随机意味着每次 运行 查询时您都会得到不同的顺序。 Unpredictable 意味着您每次都会得到相同的订单,直到您不这样做为止。
MySQL 通常忽略子查询中的 ORDER BY
子句(有一些例外,主要与子查询 LIMIT
子句有关)。将您的 ORDER BY
移至顶级查询。
编辑。您还滥用了 MySQL 对 GROUP BY
臭名昭著的非标准扩展。
你说的是给定 externalid
和 land
。因此无需按 externalid
分组;仅使用 where
子句。
与 ORDER BY
和 LIMIT
相结合,您将获得所需的记录(即,如果存在这样的记录,则为所需的语言,否则为其他语言)。
select *
from mytable
where externalid = 10
order by lang = 'fr' desc
limit 1;
更新: 好的,根据您的评论,您希望每个 externalid
获得 "best" 条记录。在标准 SQL 中,您将为此使用 ROW_NUMBER
。其他 DBMS 有进一步的解决方案,例如Oracle 的 KEEP FIRST
或 Postgre 的 DISTINCT ON
。 MySQL 不支持其中任何一个。一种方法是用变量模拟 ROW_NUMBER
。另一种方法是将上述查询用作每个 externalid
的子查询以查找最佳记录:
select *
from mytable
where id in
(
select
(
select m.id
from mytable m
where m.externalid = e.externalid
order by m.lang = 'fr' desc
limit 1
) as best_id
from (select distinct externalid from mytable) e
);