mySQL 返回错误的计数结果

Posted

技术标签:

【中文标题】mySQL 返回错误的计数结果【英文标题】:mySQL returns wrong Count result 【发布时间】:2013-11-29 04:25:10 【问题描述】:

这是我的数据库和计数查询的 sqlFiddle...

http://sqlfiddle.com/#!2/45150/6

如果我运行 select * 查询,它会返回一行,但是当我对同一个查询运行 count 时,它会给我 2 个结果...

这是对count的查询,它对“select *”产生不同的结果

SELECT count(*)
FROM (`user_info`)

JOIN `users` ON `users`.`id`=`user_info`.`user_id`

LEFT JOIN `profile` ON `users`.`id`=`profile`.`user_id`

JOIN `categories` ON `categories`.`user_id` = `users`.`id`

WHERE `users`.`is_enabled` =  1
AND `categories`.`cat_id` IN (1, 3, 4) 
AND ( 
 user_info.first_name LIKE '%bob%'  
 OR user_info.last_name LIKE '%bob%' 
 OR profile.title LIKE '%bob%' 
 OR profile.overview LIKE '%bob%'  
 )
GROUP BY `users`.`id`

【问题讨论】:

select * 为我返回 2 行:sqlfiddle.com/#!2/45150/22 @cha 因为你没有放group by users.id 【参考方案1】:

正如您所提到的,您可以将多个类别与一个用户关联。因此,在您的情况下无法使用 COUNT(*)。要修复它,您可以使用以下任一选项:

很简单,使用 SELECT COUNT(DISTINCT users.id),就像在这个 SQL Fiddle 中一样:

SELECT count(distinct `users`.`id`)
FROM (`user_info`)
JOIN `users` ON `users`.`id`=`user_info`.`user_id`
LEFT JOIN `profile` ON `users`.`id`=`profile`.`user_id`
JOIN `categories` ON `categories`.`user_id` = `users`.`id`
WHERE `users`.`is_enabled` =  1
AND `categories`.`cat_id` IN (1, 3, 4) 
AND ( 
 user_info.first_name LIKE '%bob%'  
 OR user_info.last_name LIKE '%bob%' 
 OR profile.title LIKE '%bob%' 
 OR profile.overview LIKE '%bob%'  
 )
GROUP BY `users`.`id`

但是,这只会隐藏问题。如果您开始向 select 语句中添加新的聚合函数(如 SUM(salary) 等),该问题将再次出现

我想正确的解决方案是修复重复并修改您的 FROM 子句,如下所示:

SELECT count(*)
FROM (`user_info`)
JOIN `users` ON `users`.`id`=`user_info`.`user_id`
LEFT JOIN `profile` ON `users`.`id`=`profile`.`user_id`
WHERE `users`.`is_enabled` =  1
AND ( 
 user_info.first_name LIKE '%bob%'  
 OR user_info.last_name LIKE '%bob%' 
 OR profile.title LIKE '%bob%' 
 OR profile.overview LIKE '%bob%'  
 )
AND `users`.`id` IN (SELECT `user_id` FROM `categories` WHERE `categories`.`cat_id` IN (1, 3, 4) )


GROUP BY `users`.`id`

SQL Fiddle

【讨论】:

【参考方案2】:

这是因为您是按用户 ID 分组的。

如果您想运行select *,则必须删除group by 子句。这将返回 count(*) 返回的 2 个结果。这些结果恰好具有相同的 id,因此它们仅分组为一个结果。

彻底改变问题后编辑:

OP 在评论中提到:

我想查找具有多个类别(来自搜索)的任何用户

这意味着您不能只是盲目地加入类别表。您必须首先检查用户是否分配了多个类别(与cat_id IN (1, 3, 4) 匹配)。你可以这样做:

SELECT * FROM user_info ui
JOIN `users` u ON u.id = ui.user_id
LEFT JOIN profile p ON u.id = p.user_id
JOIN (
  SELECT user_id FROM categories
  WHERE cat_id IN (1, 3, 4) 
  GROUP BY user_id
  HAVING COUNT(*) > 1
) c ON c.user_id = u.id
WHERE u.is_enabled = 1 AND ( 
  ui.first_name LIKE '%bob%' OR
  ui.last_name LIKE '%bob%' OR
  p.title LIKE '%bob%' OR
  p.overview LIKE '%bob%'  
)

小提琴here.

【讨论】:

但我只想看到一个用户?每个用户在类别表中选择了多个类别...我不想重复它们?例如,可以搜索类别 id 1、2、3 并且用户 1 在表中有 1、2、3,它会显示 3 次用户 1,我只想显示他一次??? 我已经解释了为什么wrong Count result 没有错。如果您需要特定的输出,那么您应该将其添加到问题中。无论如何,如果您只想在一行中显示用户......那么什么类别 id 将包含该行?我可以在您添加的查询中看到用户有 cat_id 4 和 1...您会选择在该行中显示哪一个,为什么? 欣赏.. 但你看,在查询中我有 JOIN categories ON categories.user_id = users.id AND categories.cat_id IN (1, 3, 4) ........ 并且 cat_id 来自数组... 由于为每个用户分配了多个类别,因此复制了行。我得到了正确的结果,问题出在计数上,我该怎么做才能使它正确? 你说I want to look for any user with more than one categories (coming from search)cat_id in (1, 3, 4) 不会为您提供您正在寻找的结果。如果它只匹配1 它会返回它但你说with more than one categories 所以它不应该 欢迎。但请记住,cha 的答案将返回匹配这三个类别中的任何一个的用户。如果您需要让它们匹配多个,则必须使用HAVING COUNT(*) > 1

以上是关于mySQL 返回错误的计数结果的主要内容,如果未能解决你的问题,请参考以下文章

CakePHP 2.9 连接查询返回错误结果

Bigquery 返回重复的行以及错误的计数

Django 多注解返回错误结果

...尝试优化 mysql innodb 表以实现快速计数仍然没有得到结果

MySQL SELECT 返回错误结果

为啥 MySQL 给出错误“不允许从函数返回结果集”?