来自GROUP BY丢失的子查询的MySQL ORDER BY

时间:2018-01-25 14:41:10

标签: mysql group-by sql-order-by

我有一张桌子x:

ID郎外部编号

1 NL 10

2 NL 11

3 FR 10

从这个表中我想要某个lang和externalid的行,如果这个lang不存在externalid,我希望该行包含任何其他语言。

子查询对表进行排序是正确的,但是当我添加组时,子查询的类型将丢失。这适用于较旧的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。

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

您的子查询生成一个传递给外部查询的结果集(虚拟表)。

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

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

MySQL通常会忽略子查询中的ORDER BY子句(有一些例外,主要与子查询LIMIT子句相关)。将您的ORDER BY移至顶级查询。

修改即可。你也在滥用MySQL对GROUP BY的臭名昭着的非标准扩展。

答案 1 :(得分:0)

您所说的是externalidland。因此无需按externalid分组;使用仅仅where条款。

结合ORDER BYLIMIT,您可以获得所需的记录(例如,如果存在此记录,则为所需语言,否则为另一种记录)。

select *
from mytable
where externalid = 10
order by lang = 'fr' desc
limit 1;

更新:好的,根据您的评论,您希望得到最好的"记录每externalid。在标准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
);