MySql错误:与sql_mode = only_full_group_by

时间:2020-01-03 20:08:50

标签: mysql sql group-by

我继承了一个生成此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

错误-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”的任意组合,这些组合可以为我提供所需的结果集吗?

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

问题:

我继承的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错误:

错误-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在功能上是依赖的...那么我们可以只包装一个聚合函数。例如: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列”的值通常 NOT 相同。尽管如此,“ MAX()”恰好满足了我们的需要:它解决了错误,并从我们拥有的模式中获得了想要的结果。

谢谢大家!