Mysql在哪里没有按预期工作

时间:2015-02-17 14:49:50

标签: mysql

我有以下查询:

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查询,则返回

  • 1 结果
  • ,值 13
  • 该列名为"test_id"

当我运行上面的整个查询时,我得到了

  • 2 来自测试表的结果......
  • 使用不同的ID ... 13 14

如果我使用数字 13 替换IN查询... SQL返回 1 结果(正确的 )。

我在这里做错了什么?

3 个答案:

答案 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,则会看到它包含14GROUP 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`

请注意selectgroup by。它们有不同的变量:

`test_wobble`.`test_id`
`wobbles`.`id`

我不确定你真正想要哪一个。但是,当您运行查询时,MySQL会返回 indeterminate 值 - 并且该值可以从一次运行更改为下一次运行。您应该修复selectgroup by,以便它们匹配。

答案 2 :(得分:0)

内部查询公开未定义的行为。它在MySQL Handling of GROUP BY页面上的文档中进行了解释。

根据SQL标准,内部查询无效。要有效,SELECTHAVINGORDER BY子句中显示的所有列都必须满足以下条件之一:

  • 它们出现在GROUP BY子句中;
  • 仅作为aggregate functions的参数使用(SELECTHAVINGORDER 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和值14test_id的行。

如果此结果集正确,则可以从test_wobble.wobble_id中删除SELECT,保留DISTINCT并将查询放入较大的结果中。

不需要GROUP BY(因为DISTINCT),如果没有它,它应该更快。