分组依据和Mysql 5.7-分组错误

分组依据和Mysql 5.7-分组错误,mysql,Mysql,我的主机将mysql版本从5.6改为5.7,只禁用了完整组,我的查询有问题 SELECT `id`, `category`, `name`, `number`, `lang` FROM `test` WHERE `category` = 'Cat1' ORDER BY FIELD(lang, 'EN', 'JP') 这显示了如下良好结果: 1 Cat1 Test1 23 EN 2 Cat1 Test2 21 EN 2 Cat1 Test1 23 JP 4 Cat1 Test1 23 JP 5

我的主机将mysql版本从5.6改为5.7,只禁用了完整组,我的查询有问题

SELECT  `id`, `category`, `name`, `number`, `lang`
FROM `test`
WHERE `category` = 'Cat1'
ORDER BY FIELD(lang, 'EN', 'JP')
这显示了如下良好结果:

1 Cat1 Test1 23 EN
2 Cat1 Test2 21 EN
2 Cat1 Test1 23 JP
4 Cat1 Test1 23 JP
5 Cat1 Test2 21 JP
SELECT *
FROM
(
SELECT  `id`, `category`, `name`, `number`, `lang`
FROM `test`
WHERE `category` = 'Cat1'
ORDER BY FIELD(lang, 'EN', 'JP')
) as table
GROUP BY number
ORDER BY number DESC
然后我对结果进行分组,只得到一个结果,如下所示:

1 Cat1 Test1 23 EN
2 Cat1 Test2 21 EN
2 Cat1 Test1 23 JP
4 Cat1 Test1 23 JP
5 Cat1 Test2 21 JP
SELECT *
FROM
(
SELECT  `id`, `category`, `name`, `number`, `lang`
FROM `test`
WHERE `category` = 'Cat1'
ORDER BY FIELD(lang, 'EN', 'JP')
) as table
GROUP BY number
ORDER BY number DESC
在mysql 5.6中,它起作用了。在5.7中没有

第5.6节的结果:

1 Cat1 Test2 21 EN
2 Cat1 Test1 23 EN
第5.7节的结果:

1 Cat1 Test2 21 JP
2 Cat1 Test1 23 EN
为什么在mysql 5.7中,GROUPBY不取第一个元素,而是随机取一个呢?

使用GROUPBY而不使用聚合函数可以任意选取值。MySQL不能保证这一点

SELECT 
T.*
FROM
`test` T
INNER JOIN
(
    SELECT  
    MIN(`id`) min_id, 
    `category`,
    `number`
    FROM `test`
    WHERE `category` = 'Cat1'
    GROUP BY `number`
) as t
ON T.`id` = t.min_id AND T.category = t.category AND t.`number` = T.`number`
ORDER BY T.number DESC;
编辑:

为了使Cat1类别下的每个数字都有一行,且lang='EN'为最高优先级:

SELECT 
*
FROM 
(
    SELECT 
    *,
    IF(@sameNumber = `number`, @rn := @rn + 1 ,
       IF(@sameNumber := `number`, @rn := 1, @rn := 1)
       ) AS groupWiseRankNumber
    FROM test 
    CROSS JOIN (SELECT @sameNumber := NULL , @rn := 1) var
    WHERE category = 'Cat1'
    ORDER BY `number` , FIELD(lang, 'EN','JP')
) AS t
WHERE t.groupWiseRankNumber <= 1;

您只是在观察MySQL文档一直以来所说的:GROUPBYQUERY的select中的非聚合列来自不确定的行。无论如何,您不应该使用此语法。这是一个MySQL的错误特性,它只会导致比它解决的问题更多的问题,并且在任何其他非MySQL派生的数据库中都不可用

以下是一种更有效的方法:

select t.*
from test t
where number = 21 and lang = 'EN'
union all
select t.*
from test t
where number = 21 and lang = 'JP' and
      not exists (select 1 from test t2 where t2.number = t.number and t2.lang = 'EN');

这可以利用testnumber、lang上的索引获得最佳性能。

在mysql 5.7中,如果所有ORDER BY都位于GROUP BY之前的子查询中,那么它们似乎都将被忽略

我的问题也一样。我找到了工作。您可以按键列添加订单。如果id是表中的主键,则可以添加

GROUP BY `id`
以前

ORDER BY FIELD(lang, 'EN', 'JP')
查询:

`SELECT *
FROM
(
  SELECT  `id`, `category`, `name`, `number`, `lang`
  FROM `test`
  WHERE `category` = 'Cat1'
  GROUP BY `id`
  ORDER BY FIELD(lang, 'EN', 'JP')
) as table
GROUP BY number
ORDER BY number DESC`
您可以使用子查询中的“限制”按工时进行排序:

或者使用GROUP_CONCAT来执行此操作:

SELECT
    `id`,
    `category`,
    `name`,
    `number`,
    SUBSTRING_INDEX(
        GROUP_CONCAT(
            lang
            ORDER BY
                FIELD(lang, 'EN', 'JP')
        ),
        ',',
        1
    ) AS lang
FROM
    `test`
WHERE
    `category` = 'Cat1'
GROUP BY
    number
ORDER BY
    number DESC

OP的示例数据返回三行,而不是一行。但后面的查询要求结果集中有一行。lang排序在哪里请检查“编辑”部分下的查询,好吗@它总是采用随机元素。这正好是你的第一个案子。这是一种行为。一般来说,在没有任何聚合函数的情况下,不应通过GROUP BY子句在子查询中添加限制1000000。在MariaDB优化了子查询中的ORDERBY子句之后,这对MariaDB起到了作用。但我不能说它是否适用于MySQL 5.7。然而,这只是一个快速修复。您应该重写所有这些查询。解决这个问题还有很多其他方法。而且大多数都更快。