mySQL 返回不应该的结果

标签 mysql left-join coalesce

我有一张 table ,里面装满了用户写的品酒笔记,还有一张 table ,里面保存着其他用户对每个品酒笔记的评分。

显示由您尚未评分的其他用户撰写的所有注释的查询如下所示:

SELECT tastingNotes.userID, tastingNotes.beerID, tastingNotes.noteID, tastingNotes.note, COALESCE(sum(tasteNoteRate.Score), 0) as count, 
CASE 
WHEN tasteNoteRate.userVoting = 1162 THEN 1 
ELSE 0
END AS userScored
FROM  tastingNotes
left join tasteNoteRate on tastingNotes.noteID = tasteNoteRate.noteID
WHERE tastingNotes.userID != 1162 
Group BY tastingNotes.noteID
HAVING userScored < 1
ORDER BY count, userScored

用户 1162 已为注释 113 编写了注释。在tasteNoteRate 表中,它显示为:

noteID | userVoting | score
  113       1162        0

但每次运行上述查询时仍然返回......

最佳答案

MySQL 允许您使用 group by以一种相当特殊的方式而不提示,请参阅 documentation :

If ONLY_FULL_GROUP_BY is disabled, a MySQL extension to the standard SQL use of GROUP BY permits the select list, HAVING condition, or ORDER BY list to refer to nonaggregated columns even if the columns are not functionally dependent on GROUP BY columns. [...] In this case, the server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate, which is probably not what you want.

此行为是 MySQL 5.7 之前的默认行为。

在您的情况下,这意味着,如果 tasteNoteRate 中有不止一行对于特定的noteID ,所以如果其他人已经投票支持该注释,userScored ,正在使用 tasteNoteRate.userVoting如果没有聚合函数,将基于随机行 - 可能是错误的。

您可以使用聚合来解决这个问题:

select ..., 
   max(CASE 
   WHEN tasteNoteRate.userVoting = 1162 THEN 1 
   ELSE 0
   END) AS userScored
from ...

或者,由于比较结果(与 null 以外的其他值)为 1 或 0,因此您还可以使用较短的版本:

select ..., 
   coalesce(max(tasteNoteRate.userVoting = 1162),0) AS userScored
from ...

要准备升级到 MySQL 5.7(并启用 ONLY_FULL_GROUP_BY ),您还应该已经 group by select 中的所有非聚合列-列表:group by tastingNotes.userID, tastingNotes.beerID, tastingNotes.noteID, tastingNotes.note .

编写查询(以及其他查询)的另一种方式是对 tastingNoteRates 进行分组。在子查询中,因此您不必 group by tastingNotes 的所有列:

select tastingNotes.*, 
       coalesce(rates.count, 0) as count, 
       coalesce(rates.userScored,0) as userScored
from tastingNotes
left join (
  select tasteNoteRate.noteID,
         sum(tasteNoteRate.Score) as count,
         max(tasteNoteRate.userVoting = 1162) as userScored
  from tasteNoteRate
  group by tasteNoteRate.noteID
) rates 
on tastingNotes.noteID = rates.noteID and rates.userScored = 0
where tastingNotes.userID != 1162 
order by count;

这还允许您通过更改 rates.userScored = 0 来获取用户投票的注释在 on -条款= 1 (或删除它以获得两者)。

关于mySQL 返回不应该的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42639328/

相关文章:

java - 在 JAVA 中将数据从文本文件传输到 MySQL 表时出现 OutOfMemory 错误

php - 将参数绑定(bind)传递给 Laravel 查询生成器?

sql - 选择缺少行或零值的查询?

mysql - 当 sql 中的大小写在 cassandra cql 中不支持时

mysql 复杂的sql

MySQL 连接想要排除不在第二个表中的行

MySQL left join fill with previous value if null

mysql - 如何确保没有数据的类别仍然出现在 SQL 输出中

mysql - 无法使用 mysql 增加空集

r - 在 dplyr::coalesce 中传递一个字符串作为变量名