【问题标题】:MySql error: incompatible with sql_mode=only_full_group_byMySql 错误:与 sql_mode=only_full_group_by 不兼容
【发布时间】:2020-01-03 20:08:50
【问题描述】:

我继承了生成此 SQL 的 CodeIgniter 查询

示例:

SELECT `users`.`id`, `users`.`username`, `users`.`email`, `users`.`photo`, `users`.`rating`
FROM `pool_details`
JOIN `users` ON `users`.`id` = `pool_details`.`captain_id`
WHERE `pool_details`.`pool_type` =0
AND `pool_details`.`pool_close` > '2020-01-02 18:39:42'
GROUP BY `pool_details`.`captain_id`
ORDER BY `pool_details`.`members_count` DESC
LIMIT 20

ERROR - 2020-01-02 18:39:42 --> 查询错误:ORDER BY 的表达式 #1 子句不在 GROUP BY 子句中并且包含非聚合列 'pool_details.members_count' 这不是功能 依赖于 GROUP BY 子句中的列;这与 sql_mode=only_full_group_by - 无效查询:

以下是相同的数据,其中包含一些“额外的列”并删除了违规子句:

SELECT users.id, users.username, users.email,users.rating,pool_details.members_count,pool_details.pool_type,pool_details.pool_close
FROM  pool_details
JOIN  users ON users.id = pool_details.captain_id
WHERE pool_details.pool_type = 0 AND pool_details.pool_close > '2020-01-02 18:39:42'
ORDER BY pool_details.members_count DESC;
//GROUP BY `pool_details`.`captain_id`
+----+----------+--------------------------+--------+---------------+-----------+---------------------+
| id | username | email                    | rating | members_count | pool_type | pool_close          |
+----+----------+--------------------------+--------+---------------+-----------+---------------------+
| 13 | Ronaldo  | pulisicblues07@gmail.com | 4.6    |           100 | 0         | 2020-01-04 03:00:00 |
| 13 | Ronaldo  | pulisicblues07@gmail.com | 4.6    |           100 | 0         | 2020-01-03 23:30:00 |
| 13 | Ronaldo  | pulisicblues07@gmail.com | 4.6    |           100 | 0         
...
| 13 | Ronaldo  | pulisicblues07@gmail.com | 4.6    |             0 | 0         | 2020-01-03 00:00:00 |
| 13 | Ronaldo  | pulisicblues07@gmail.com | 4.6    |             0 | 0         | 2020-01-03 00:30:00 |
| 13 | Ronaldo  | pulisicblues07@gmail.com | 4.6    |             0 | 0         | 2020-01-04 21:30:00 |
| 13 | Ronaldo  | pulisicblues07@gmail.com | 4.6    |             0 | 0         | 2020-01-03 03:00:00 |
+----+----------+--------------------------+--------+---------------+-----------+---------------------+
28 rows in set (0.00 sec)

我想要的是:

  1. 显示用户的用户名、电子邮件和评分
  2. 按“members_count”排序
  3. 只向用户显示一次

例如:

SELECT DISTINCT users.id, users.username, users.email,users.rating
FROM  pool_details
JOIN  users ON users.id = pool_details.captain_id
WHERE pool_details.pool_type = 0 AND pool_details.pool_close > '2020-01-02 18:39:42';
+----+----------+--------------------------+--------+
| id | username | email                    | rating |
+----+----------+--------------------------+--------+
|  5 | wheel    | wheel@boxpik.com         | NULL   |
| 13 | Ronaldo  | pulisicblues07@gmail.com | 4.6    |
+----+----------+--------------------------+--------+
2 rows in set (0.00 sec)
<= This shows the users individually ... but it's *NOT* ordered by "members_count".

问:我可以在 mySql 5.7 中使用“GROUP BY”和/或“DISTINCT”的任何组合来获得我需要的结果集吗?

【问题讨论】:

  • 如果我们知道members_count 是功能相关的(即我们知道折叠组中所有行中members_count 列的值相同),那么我们可以包装在一个聚合函数中。例如ORDER BY MAX(pool_details.members_count) DESC。 (我们可以使用 MIN() 代替 MAX(),结果将是相同的,如果我们保证折叠组中的所有行具有相同的值 members_count,那么我们知道 MIN(members_count) &lt;=&gt; MAX(members_count)
  • 您想在 ORDER BY 中使用用户可能拥有的所有“members_count”?
  • @spencer7593:这就是解决方案!谢谢!这是我更新的 SQL。如果您发布答案;我很乐意投票并“接受”它。 SELECT users.id, users.username, users.email,users.rating FROM pool_details JOIN users ON users.id = pool_details.captain_id WHERE pool_details.pool_type = 0 AND pool_details.pool_close &gt; '2020-01-02 18:39:42' GROUP BY pool_details.captain_id ORDER BY MAX(pool_details.members_count) DESC;
  • @FoggyDay:我的评论不是对所问问题的回答,如果 GROUP BY 和 DISTINCT 的组合......如果members_count 在功能上不依赖,那么回应来自的评论forpas,我们要使用members_count 的哪些可能值?使用 MAX 和 MIN 选择最大值和最小值很容易,但也许我们想要与最早或最新的 pool_close 关联的值......我们只是在猜测,因为我们没有;没有更精确的规范
  • 叹息...我没有说“和”;我说“和/或”。从某种意义上说,“任何语法都可以消除错误”。你给了我答案:“MAX()”。这个答案是有道理的:我们想要一个aggregate。具体来说:成员最多的队长上,第二多的队长,等等。如果你给出回应,我会“接受”它。

标签: mysql sql group-by


【解决方案1】:

除了ORDER BY,您似乎只想要EXISTS。也就是说,您可以在ORDER BY 中使用另一个子查询:

SELECT u.*
FROM users u
WHERE EXISTS (SELECT 1
              FROM pool_details pd
              WHERE pd.captain_id = u.id AND
                    pd.pool_type = 0 AND
                    pd.pool_close > '2020-01-02 18:39:42'
             )
ORDER BY (SELECT MAX(pd2.members_count)
          FROM pool_details pd2
          WHERE pd2.captain_id = u.id AND
                pd2.pool_type = 0 AND
                pd2.pool_close > '2020-01-02 18:39:42'
         ) DESC
LIMIT 20

编辑:

你也可以这样写:

SELECT u.*,
       (SELECT MAX(pd2.members_count)
        FROM pool_details pd2
        WHERE pd2.captain_id = u.id AND
              pd2.pool_type = 0 AND
              pd2.pool_close > '2020-01-02 18:39:42'
      ) as max_members_count
FROM users u
HAVING max_member_count IS NOT NULL
ORDER BY max_member_count DESC
LIMIT 20

或者:

SELECT u.*
FROM users u JOIN
     (SELECT pd2.captain_id, MAX(pd2.members_count) as max_member_count
      FROM pool_details pd2
      WHERE pd2.pool_type = 0 AND
            pd2.pool_close > '2020-01-02 18:39:42'
     ) pd
     ON pd.captain_id = u.id
ORDER BY max_member_count DESC
LIMIT 20l

【讨论】:

  • 谢谢。我冒昧地修正了第二个子选择中的错字,并将u.* 更改为SELECT u.id, u.username, u.email, u.rating。在这一点上,它正是我想要的。问:“where exists()”和两个子选择不是效率低下吗?仅供参考,我 ALSO 能够使用 spencer7593 的建议修复 SQL 错误并获得我想要的结果:ORDER BY MAX(pool_details.members_count)。这不是更有效率吗?
  • @FoggyDay 。 . .我添加了两个等效的方法。老实说,当我回答问题并返回并添加到子查询中时,我并没有注意到ORDER BY。使用适当的索引,这可能是一个好方法,尽管编辑中的第一个查询可能具有最佳性能。
【解决方案2】:

问题:

我继承的一个 PHP/CodeIgniter 应用程序生成了这个 SQL:

SELECT `users`.`id`, `users`.`username`, `users`.`email`, `users`.`photo`, `users`.`rating`
FROM `pool_details`
JOIN `users` ON `users`.`id` = `pool_details`.`captain_id`
WHERE `pool_details`.`pool_type` =0
AND `pool_details`.`pool_close` > '2020-01-02 18:39:42'
GROUP BY `pool_details`.`captain_id`
ORDER BY `pool_details`.`members_count` DESC
LIMIT 20

.. 这反过来又导致了这个 MySql 错误:

ERROR - 2020-01-02 18:39:42 --> 查询错误:ORDER BY 的表达式 #1 子句不在 GROUP BY 子句中并且包含非聚合列 'pool_details.members_count' 在功能上不依赖于 GROUP BY 子句中的列;这与 sql_mode=only_full_group_by - 无效查询:

原因:

forpas 提出了正确的问题:

您想在 ORDER BY 中使用用户可能拥有的所有“members_count”?

spencer7593 给出了正确的解决方案:

如果我们知道 members_count 在功能上是依赖的……那么我们可以只包装一个聚合函数。 .e.g ORDER BY MAX(pool_details.members_count) DESC。

解决方案:

修改 PHP/CodeIgniter 查询:

$this->db->select('users.id,users.username,users.email,users.photo,users.rating');
$this->db->from('pool_details');
$this->db->join('users','users.id = pool_details.captain_id');
$this->db->where('pool_details.pool_type',0);
$this->db->where('pool_details.pool_close >',$now);
$this->db->order_by('MAX(pool_details.members_count)','DESC'); // <-- Added "MAX()"
$this->db->group_by('pool_details.captain_id');
$this->db->limit(20, 0);
$query = $this->db->get()->result();

讨论: 每个“池”都有一个“队长”。

我们希望将所有池中所有队长中的每个队长“分组”。

列表的顶部应该是成员最多的池。

聚合MAX(pool_details.members_count) 为我们提供了我们正在寻找的结果。

没有“功能依赖”;折叠组中所有行的“members_count 列”的值通常相同。然而,“MAX()”完全符合我们的需要:它解决了错误,并且我们从现有的模式中得到了我们想要的结果。

谢谢大家!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-12
    • 2017-05-12
    • 2016-07-12
    • 2020-02-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多