MySQL ORDER BY from子查询按GROUP BY丢失

MySQL ORDER BY from子查询按GROUP BY丢失,mysql,group-by,sql-order-by,Mysql,Group By,Sql Order By,我有一张桌子: idRangeExternalId 1nl10 2nl11 3fr10 从这个表中,我想要某个lang和externalid的所有行,如果这个lang不存在externalid,我想要该行和任何其他lang 子查询对表进行正确排序,但当我添加group by时,子查询的排序将丢失。这适用于较旧的mysql版本,但不适用于5.7 ( SELECT * FROM x ORDER BY FIELD(lang, "fr") DESC, id ) as y group by

我有一张桌子:

idRangeExternalId

1nl10

2nl11

3fr10

从这个表中,我想要某个lang和externalid的所有行,如果这个lang不存在externalid,我想要该行和任何其他lang

子查询对表进行正确排序,但当我添加group by时,子查询的排序将丢失。这适用于较旧的mysql版本,但不适用于5.7

(
 SELECT
  *
 FROM
  x
 ORDER BY FIELD(lang, "fr") DESC, id
)
 as y
group by externalid
我希望查询返回id为2和3的记录。因此,对于每个不同的外部id,如果可能,lang='fr',否则任何其他lang


如何解决此问题?

子查询将生成一个结果集(虚拟表),并将其传递给外部查询

除非在
orderby
子句中完全指定顺序,否则所有SQL查询都会毫无例外地以不可预测的顺序生成结果

不可预测就像是随机的,只是更糟。Random意味着每次运行查询时都会得到不同的顺序。不可预测意味着你每次都会得到相同的订单,直到你没有

MySQL通常忽略子查询中的
orderby
子句(有一些例外,主要与子查询
LIMIT
子句有关)。将您的
订单按
移动到顶层查询


编辑。您还误用了MySQL臭名昭著的对
groupby
的非标准扩展

您所说的是给定的
externalid
land
。无需按
externalid
进行分组;只使用
where
子句

结合
ORDER BY
LIMIT
可以获得所需的记录(即,如果存在这样的记录,则使用所需的语言,否则使用另一种语言)

更新:好的,根据您的评论,您希望根据
externalid
获得“最佳”记录。在标准SQL中,您将为此使用
行数
。其他数据库管理系统有进一步的解决方案,例如Oracle的
保持优先
或Postgre的
上进行区分。MySQL不支持任何这些。一种方法是用变量模拟
行数
。另一种方法是根据
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
);

不要认为通过外部查询删除订单会有所帮助。。因为MySQL将在ORDER BY之前运行GROUP BY..谢谢您的帮助。由于您解释的原因,将ORDER BY移动到顶级查询并不能解决问题。请修复您发布的SQL查询。此SQL查询是无效的SQL。。同时发布您期望的结果请告诉我们您希望显示的内容,特别是当您
按外部ID分组时。您的group by子句实际上没有什么意义。“某个lang和externalid的所有行”-这是否意味着与您的示例不同,一个
lang
externalid
可以有多个记录(例如,两个记录,都带有
lang=nl和externalid=10
)?您想选择所有这些记录吗?如果没有与给定的
lang
externalid
匹配的记录,那么您需要一个具有给定
externalid
的结果记录,无论哪个
lang
,都不能有两个具有相同lang和externalid的记录。第二部分是正确的。我想要一个带有给定externalid和lang的结果。如果没有带有lang的记录,那么externalid将带有任意lang。我没有正确地表达我自己。我想要不同外部ID的所有记录。我希望查询返回问题中id为2和3的记录。好的,这在MySQL中有点复杂。我在回答中添加了一个问题。此查询多次访问该表。另一种选择是使用变量。您将在其他SO线程中找到此方法。感谢您的解决方案!但是查询速度很慢。如果我使用变量,查询会更快吗?可能会。您只需选择一次记录,并使用变量对每个外部ID的记录进行编号(如果存在“fr”记录,则为1);然后你保留所有#1记录,不用再看表就可以完成。这是正确的方法吗?还是可以做得更好选择*FROM(选择@prev_externalid:=@externalid作为prev_externalid,@externalid:=externalid作为externalid,@externalid作为externalid作为externalid,@externalid作为externalid作为externalid,@externalid作为externalid,@externalid作为externalid,@externalid作为externalid的索引:=0)作为externalid_索引,tbl_seo.*从mytable ORDER BY externalid ASC,lang='fr'DESC)作为mytable,其中externalid_索引=0`
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
);