【问题标题】:mySQL returns wrong Count resultmySQL 返回错误的计数结果
【发布时间】: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`

【问题讨论】:

标签: mysql sql


【解决方案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
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-30
    相关资源
    最近更新 更多