我有以下查询:
SELECT
`tests`.`id`,
`tests`.`created_at`,
`tests`.`updated_at`,
`tests`.`created_by`,
`tests`.`date_of_test`,
`tests`.`location`,
`tests`.`information`,
`tests`.`title`,
`tests`.`goals`,
`tests`.`deleted_at`,
`tests`.`status`,
`tests`.`tester`,
`tests`.`test_approach`
FROM `tests`
WHERE
`tests`.`id` IN (
SELECT `test_wobble`.`test_id`
FROM `project_wobble`
INNER JOIN `wobbles` ON `project_wobble`.`wobble_id` = `wobbles`.`id`
INNER JOIN `wobble_profiles` ON `wobble_profiles`.`wobble_id` = `wobbles`.`id`
INNER JOIN `wobble_profile_user` ON `wobble_profile_user`.`wobble_profile_id` = `wobble_profiles`.`id`
INNER JOIN `test_wobble` ON `test_wobble`.`wobble_id` = `wobbles`.`id`
WHERE `project_wobble`.`project_id` = '2' AND `wobble_profile_user`.`user_id` = '3'
GROUP BY `wobbles`.`id`
)
GROUP BY `tests`.`id`
ORDER BY tests.date_of_test DESC
如果我自己运行IN
查询,则返回
"test_id"
当我运行上面的整个查询时,我得到了
如果我使用数字 13 替换IN
查询... SQL返回 1 结果(正确的 )。
我在这里做错了什么?
答案 0 :(得分:1)
此查询:
SELECT `test_wobble`.`test_id`
FROM `project_wobble`
INNER JOIN `wobbles` ON `project_wobble`.`wobble_id` = `wobbles`.`id`
INNER JOIN `wobble_profiles` ON `wobble_profiles`.`wobble_id` = `wobbles`.`id`
INNER JOIN `wobble_profile_user` ON `wobble_profile_user`.`wobble_profile_id` = `wobble_profiles`.`id`
INNER JOIN `test_wobble` ON `test_wobble`.`wobble_id` = `wobbles`.`id`
WHERE `project_wobble`.`project_id` = '2' AND `wobble_profile_user`.`user_id` = '3'
GROUP BY `wobbles`.`id`
按wobbles.id
分组,但返回test_wobble.test_id
,而GROUP BY
不属于MySQL
。
在每次迭代中,SELECT `test_wobble`.`test_id`
FROM `project_wobble`
INNER JOIN `wobbles` ON `project_wobble`.`wobble_id` = `wobbles`.`id`
INNER JOIN `wobble_profiles` ON `wobble_profiles`.`wobble_id` = `wobbles`.`id`
INNER JOIN `wobble_profile_user` ON `wobble_profile_user`.`wobble_profile_id` = `wobble_profiles`.`id`
INNER JOIN `test_wobble` ON `test_wobble`.`wobble_id` = `wobbles`.`id`
WHERE `project_wobble`.`project_id` = '2' AND `wobble_profile_user`.`user_id` = '3'
-- This is implicitly added by MySQL when optimizing
AND `test_wobble`.`test_id` = `tests`.`id`
GROUP BY `wobbles`.`id`
将IN字段推送到此查询中:
GROUP BY
然后只检查是否存在某个值。
如果您从IN
查询中删除了13
,则会看到它包含14
和GROUP BY
,但只有其中一个会在您返回时返回使用tests.id
运行查询。
你也可以尝试运行第二个查询,用13和14代替MySQL
,并确保查询在两种情况下都返回。
这实际上可能被视为{{1}}中的错误。但是,由于文档没有指定从分组查询中返回哪个未分组和未分解的表达式,因此最好明确指定它,优化器的副作用将像这样的情况一样启动。
您能否提供一些数据样本,并概述您将通过查询实现的目标?
答案 1 :(得分:0)
在不知道数据是什么的情况下,有点难以辨别。但是,子查询中确实存在问题。这是你的子查询:
SELECT `test_wobble`.`test_id`
FROM `project_wobble` INNER JOIN
`wobbles`
ON `project_wobble`.`wobble_id` = `wobbles`.`id` INNER JOIN
`wobble_profiles`
ON `wobble_profiles`.`wobble_id` = `wobbles`.`id` INNER JOIN
`wobble_profile_user`
ON `wobble_profile_user`.`wobble_profile_id` = `wobble_profiles`.`id` INNER JOIN
`test_wobble`
ON `test_wobble`.`wobble_id` = `wobbles`.`id`
WHERE `project_wobble`.`project_id` = '2' AND `wobble_profile_user`.`user_id` = '3'
GROUP BY `wobbles`.`id`
请注意select
和group by
。它们有不同的变量:
`test_wobble`.`test_id`
`wobbles`.`id`
我不确定你真正想要哪一个。但是,当您运行查询时,MySQL会返回 indeterminate 值 - 并且该值可以从一次运行更改为下一次运行。您应该修复select
和group by
,以便它们匹配。
答案 2 :(得分:0)
内部查询公开未定义的行为。它在MySQL Handling of GROUP BY页面上的文档中进行了解释。
根据SQL标准,内部查询无效。要有效,SELECT
,HAVING
和ORDER BY
子句中显示的所有列都必须满足以下条件之一:
GROUP BY
子句中; SELECT
,HAVING
或ORDER BY
); GROUP BY
列。例如,使用您的表格,您可以输入SELECT
子句:
wobbles.id
- 因为它出现在GROUP BY
子句中; COUNT(DISTINCT project_wobble.project_id)
- 即使project_wobble.project_id
中未显示GROUP BY
,也可以将其用作汇总函数COUNT(DISTINCT)
的参数; wobbles
的任意列,假设列id
是其PK
- 表wobbles
的所有列都在功能上依赖于wobbles.id
(它们的值由wobbles.id
)的值唯一确定。在5.7.5版之前,MySQL接受的查询不符合上述要求,但正如文档所述:
在这种情况下,服务器可以自由选择每个组中的任何值,因此除非它们相同,否则所选的值是不确定的,这可能不是您想要的。
从版本5.7.5开始,MySQL将功能依赖性检测作为可配置功能(默认情况下打开)实现。
在5.7.5上,您的内部查询将触发错误并且全部错误;您的查询无效,因此根本无法运行。
在以前的版本上(如果禁用ONLY_FULL_GROUP_BY
SQL mode,也在5.7.5上),查询会运行,但其结果是不可预测的。例如,如果删除一行然后重新插入,则它们可以从一次执行更改为下一次执行。
由于MySQL查询优化器会重新组织整个查询以获得更好的执行计划,因此当它嵌入到较大的查询中时,其执行与独立运行时的执行不同。这是您可以观察其未定义行为的另一种方式。
提取内部查询,删除GROUP BY
子句,在SELECT
子句中添加更多列,并查看它产生的内容:
SELECT DISTINCT `test_wobble`.`wobble_id`, `test_wobble`.`test_id`
FROM `project_wobble`
INNER JOIN `wobbles` ON `project_wobble`.`wobble_id` = `wobbles`.`id`
INNER JOIN `wobble_profiles` ON `wobble_profiles`.`wobble_id` = `wobbles`.`id`
INNER JOIN `wobble_profile_user` ON `wobble_profile_user`.`wobble_profile_id` = `wobble_profiles`.`id`
INNER JOIN `test_wobble` ON `test_wobble`.`wobble_id` = `wobbles`.`id`
WHERE `project_wobble`.`project_id` = '2' AND `wobble_profile_user`.`user_id` = '3'
如果我没错,它会为列wobble_id
生成两行具有相同13
和值14
和test_id
的行。
如果此结果集正确,则可以从test_wobble.wobble_id
中删除SELECT
,保留DISTINCT
并将查询放入较大的结果中。
不需要GROUP BY
(因为DISTINCT
),如果没有它,它应该更快。