【问题标题】:PHP - Join statement duplicates recordsPHP - 加入语句重复记录
【发布时间】:2014-09-21 08:06:15
【问题描述】:

我有一个相当大的查询,它基本上向我的用户显示了我存储在数据库中的不同论坛:

    $stmt = $dbh->prepare("
    SELECT 
        c.forum_id as category_id,
        c.forum_name as category_name,
        t.forum_id as id,
        t.forum_name as name,
        t.forum_desc as description,
        (SELECT COUNT(*) FROM forum_topics WHERE forum_id=t.forum_id AND topic_deleted=0) as topics_count,
        (SELECT COUNT(*) FROM forum_posts WHERE forum_id=t.forum_id AND post_deleted=0) as posts_count,
        (SELECT COUNT(*) FROM forum_posts WHERE topic_id=lp.topic_id AND post_deleted=0) as last_post_count,
        lp.topic_id as last_post_topic_id,
        lp.topic_title as last_post_topic_title,
        lp.post_time as last_post_time,
        lp.username as last_post_username
    FROM forum_cats as t
    JOIN forum_cats as c on c.forum_id = t.forum_type_id
    left join (
        SELECT 
            ft.topic_id,
            ft.title as topic_title,
            tmp.post_time,
            u.username,
            fp.forum_id
        FROM
            forum_posts fp
            join forum_topics ft on ft.topic_id = fp.topic_id
            join users u on u.id = fp.userid
            join (
                select forum_id, max(`post_time`) `post_time`
                from forum_posts fp
                where fp.post_deleted = 0
                group by forum_id
                ) as tmp on (fp.forum_id = tmp.forum_id and fp.post_time = tmp.post_time)
        where post_deleted = 0 and ft.topic_deleted = 0
    ) as lp on lp.forum_id = t.forum_id
    where t.forum_active = 1 and c.forum_active = 1
    order by category_id, t.forum_id
");

    $stmt->execute();

然后我做一个while循环来显示所有记录:

while (($row = $stmt->fetch())) {
echo $row['name']; 
}

问题是,在 while 循环期间,我得到了很好的结果有时

应该是这样的:

forum1
forum2
forum3
forum4
forum5
forum6

等等

但有时我会得到这样的结果:

forum1
forum1
forum1
forum1
forum2
forum3
forum4
forum5
forum6

某些行(哪一行是非常随机的)正在“复制”。

有人可以帮我解释一下吗?

【问题讨论】:

  • 想必查询SELECT t.forum_id FROM forum_topics t会产生同样的错误?
  • @Strawberry 你愿意详细说明吗?
  • 只是一个疯狂的猜测,但是......我会说你的第三个加入(子查询)在主查询上带来了帖子,因为你可能在一个论坛上有很多帖子。你能单独运行子查询(你把它命名为lp)并检查是否有重复的forum_id字段?
  • 只是试图确定问题出在 PHP 还是 MySQL 上
  • 这个连接看起来很奇怪:FROM forum_cats as t JOIN forum_cats as c on c.forum_id = t.forum_type_id。什么是forum_cats(类别?),为什么需要通过 forum_id 和 type_id 加入该表本身?它看起来像一个错误,即使不是,它也可能返回重复项。

标签: php mysql sql pdo inner-join


【解决方案1】:

尝试通过添加GROUP BY t.forum_id进行分组:

SELECT 
    c.forum_id as category_id,
    c.forum_name as category_name,
    t.forum_id as id,
    t.forum_name as name,
    t.forum_desc as description,
    (SELECT COUNT(*) FROM forum_topics WHERE forum_id=t.forum_id AND topic_deleted=0) as topics_count,
    (SELECT COUNT(*) FROM forum_posts WHERE forum_id=t.forum_id AND post_deleted=0) as posts_count,
    (SELECT COUNT(*) FROM forum_posts WHERE topic_id=lp.topic_id AND post_deleted=0) as last_post_count,
    lp.topic_id as last_post_topic_id,
    lp.topic_title as last_post_topic_title,
    lp.post_time as last_post_time,
    lp.username as last_post_username
FROM forum_cats as t
JOIN forum_cats as c on c.forum_id = t.forum_type_id
left join (
    SELECT 
        ft.topic_id,
        ft.title as topic_title,
        tmp.post_time,
        u.username,
        fp.forum_id
    FROM
        forum_posts fp
        join forum_topics ft on ft.topic_id = fp.topic_id
        join users u on u.id = fp.userid
        join (
            select forum_id, max(`post_time`) `post_time`
            from forum_posts fp
            where fp.post_deleted = 0
            group by forum_id
            ) as tmp on (fp.forum_id = tmp.forum_id and fp.post_time = tmp.post_time)
    where post_deleted = 0 and ft.topic_deleted = 0
) as lp on lp.forum_id = t.forum_id
where t.forum_active = 1 and c.forum_active = 1
GROUP BY t.forum_id
order by category_id, t.forum_id

【讨论】:

  • 或者把第一个SELECT改成SELECT DISTINCT。毕竟,如果没有什么可聚合的,你为什么要分组呢?无论哪种方式,这都会消除症状,但在许多情况下,意外的重复行表示需要解决的错误。现在你只是在抑制症状。
  • 如果你添加GROUP BY,它应该在ORDER BY之前。
猜你喜欢
  • 2019-05-31
  • 1970-01-01
  • 1970-01-01
  • 2020-04-18
  • 2019-10-04
  • 1970-01-01
  • 2015-05-30
  • 2023-04-09
  • 2012-08-09
相关资源
最近更新 更多