查询:
SELECT
MIN(main_table.id) as id,
COALESCE(used_options.used, 0) AS used,
COALESCE(forced_options.force_option, 0) AS force_option
FROM main_table
LEFT JOIN (
SELECT
used_options.id id,
1 AS used
FROM main_table AS used_options
WHERE used_options.id = 20
) AS used_options
ON used_options.id = main_table.id
LEFT JOIN (
SELECT
test.id,
1 AS force_option
FROM main_table AS test
WHERE test.id = 10
) AS forced_options
ON forced_options.id = main_table.id
GROUP BY main_table.id
HAVING (used IS NOT NULL AND used > 0)
OR (force_option IS NOT NULL AND force_option = 1);
在MySQL 5.7.19(docker image mysql:5.7.19)上,我得到了:
+-----+------+--------------+
| id | used | force_option |
+-----+------+--------------+
| 1 | 0 | 0 |
| 2 | 0 | 0 |
| 3 | 0 | 0 |
| 4 | 0 | 0 |
| 5 | 0 | 0 |
| 6 | 0 | 0 |
| 10 | 0 | 1 |
| 20 | 1 | 0 |
+-----+------+--------------+
在MySQL 5.6.37上(docker image mysql:5.6.37)我得到:
+-----+------+--------------+
| id | used | force_option |
+-----+------+--------------+
| 10 | 0 | 1 |
| 20 | 1 | 0 |
+-----+------+------+------+--------------+
用于创建和填充表格的示例数据:
CREATE TABLE main_table
(
id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
fk_1 INT NOT NULL,
fk_2 VARCHAR(45) NOT NULL
);
INSERT INTO main_table (id, fk_1, fk_2) VALUES (1, 1, '2');
INSERT INTO main_table (id, fk_1, fk_2) VALUES (2, 1, '4');
INSERT INTO main_table (id, fk_1, fk_2) VALUES (3, 1, '5');
INSERT INTO main_table (id, fk_1, fk_2) VALUES (4, 1, '7');
INSERT INTO main_table (id, fk_1, fk_2) VALUES (5, 1, '10');
INSERT INTO main_table (id, fk_1, fk_2) VALUES (6, 1, '20');
INSERT INTO main_table (id, fk_1, fk_2) VALUES (10, 1, '34');
INSERT INTO main_table (id, fk_1, fk_2) VALUES (20, 1, '23');
这两个版本的MySQL之间发生了什么变化?看起来HAVING
子句在此特定查询的较新版本中被忽略。
这个区域有一些BC?
答案 0 :(得分:1)
以下是问题的症结所在:
GROUP BY main_table.id
您按一列进行分组,但选择了许多非聚合列:
SELECT
main_table.id,
main_table.fk_2,
main_table.fk_1,
COALESCE(used_options.used, 0) AS used,
COALESCE(forced_options.force_option, 0) AS force_option
此处的问题是, used
和force_option
的值被用于每个id
并不明确。
我建议,尽管你看到了,但在为查询计算每个used
组时,MySQL实际上对force_option
和1
id
值使用了非零值在MySQL 5.7.19上运行。对于在MySQL 5.6.37上运行的查询,这没有发生,并且HAVING
子句除了两条记录之外的所有条目都被过滤掉了,这是我们通过浏览表数据所期望的。
这里真正的罪魁祸首是MySQL的ONLY_FULL_GROUP_BY
模式,当关闭时,它允许这些不严格的查询选择也使用GROUP BY
的非聚合列。最好的长期修复是您重构查询,这样您就不需要选择非聚合列。
https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html