从3个MySQL表中选择帖子,用户详细信息和投票

时间:2014-03-05 06:31:10

标签: mysql left-join

我有一个用户表,其中包含ID,用户名,电子邮件等。

带有id,uid(用户ID),内容等

发布表 带有id,uid,pid(帖子ID),投票(ENUM:'1'和'-1')的

投票表格。

在投票表的投票栏中,1表示投票,-1表示投票。

我希望选择十个帖子,其中包含用户详细信息,不包括upvotes和downvotes。我尝试使用下表,但它不起作用。它为某些ID提供了多余的结果。

select 
    p.id,
    p.uid,
    p.post,
    u.username,
    count(puv.pid) as upvotes,
    group_concat(puv.uid) upvoteIds,
    count(pdv.pid) as downvotes,
    group_concat(pdv.uid) downvoteIds
from
    posts p
        join
    user u ON u.id = p.uid
        left join
    postvotes puv ON puv.pid = p.id and puv.vote = '1'
        left join
    postvotes pdv ON pdv.pid = p.id and pdv.vote = '-1'
where
    p.deleted = 0
group by u.username , p.created , p.post , p.id , p.uid
order by p.created DESC
limit 0 , 10

查询结果:

+----+-----+--------+----------+---------+-----------+-----------+-------------+
| id | uid |  post  | username | upvotes | upvoteIds | downvotes | downvoteIds |
+----+-----+--------+----------+---------+-----------+-----------+-------------+
| 19 | 2   | Post 1 | john     | 2       | 3,3       | 2         | 1,2         |
| 18 | 1   | Post 2 | dinesh   | 2       | 3,1       | 0         | NULL        |
| 17 | 3   | Post 3 | sudeep   | 0       | NULL      | 1         | 3           |
+----+-----+--------+----------+---------+-----------+-----------+-------------+

第一行为 upvoteIds upvotes 提供重复的ID为2.此处,upvotes应为1,因为id为19的帖子只有1个upvote。请查看以下投票表:

+----+-----+-----+------+
| id | pid | uid | vote |
+----+-----+-----+------+
| 1  | 19  | 3   | 1    |
| 2  | 18  | 3   | 1    |
| 3  | 17  | 3   | -1   |
| 4  | 19  | 1   | -1   |
| 5  | 18  | 1   | 1    |
| 6  | 19  | 2   | -1   |
+----+-----+-----+------+

更新

帖子

+----+-----+--------+
| id | uid |  post  |
+----+-----+--------+
| 17 | 3   | post 3 |
| 18 | 1   | post 2 |
| 19 | 2   | post 1 |
+----+-----+--------+

1 个答案:

答案 0 :(得分:2)

我总是建议从包含最终需要分组的数据的表开始,在这种情况下是postvotes表。

# upvotes
SELECT puv.pid, count(puv.vote) as upvote
FROM postvotes puv
WHERE puv.vote = 1
GROUP BY puv.pid

这应该为您提供以下数据:

+-----+--------+
| pid | upvote |
+-----+--------+
| 19  | 1      |
| 18  | 2      |
+-----+--------+

# downvotes
SELECT pdv.pid, count(pdv.vote) as downvote
FROM postvotes pdv
WHERE pdv.vote = -1
GROUP BY pdv.pid

这将为您提供以下数据:

+-----+----------+
| pid | downvote |
+-----+----------+
| 17  | 1        |
| 19  | 2        |
+-----+----------+

现在,在一个查询中将它们组合在一起:

SELECT pv.pid, uv.upvote, dv.downvote
FROM postvotes pv
LEFT JOIN
(
    SELECT puv.pid, count(puv.vote) as upvote
    FROM postvotes puv
    WHERE puv.vote = 1
    GROUP BY puv.pid
) uv
ON pv.pid = uv.pid
LEFT JOIN
(
    SELECT pdv.pid, count(pdv.vote) as downvote
    FROM postvotes pdv
    WHERE pdv.vote = -1
    GROUP BY pdv.pid
) dv
ON pv.pid = dv.pid

这应该产生以下数据:

+-----+--------+----------+
| pid | upvote | downvote |
+-----+--------+----------+
| 19  | 1      | 2        |
| 18  | 2      | NULL     |
| 17  | NULL   | 1        |
+-----+--------+----------+

现在剩下的就是加入post和user表来获取你所追求的其他数据,并在where子句中添加其他条件,例如:

SELECT p.id, p.uid, p.post, u.username, uv.upvote, dv.downvote
FROM posts p
JOIN users u ON p.uid = u.id
LEFT JOIN
(
    SELECT puv.pid, count(puv.vote) as upvote
    FROM postvotes puv
    WHERE puv.vote = 1
    GROUP BY puv.pid
) uv
ON p.id = uv.pid
LEFT JOIN
(
    SELECT pdv.pid, count(pdv.vote) as downvote
    FROM postvotes pdv
    WHERE pdv.vote = -1
    GROUP BY pdv.pid
) dv
ON p.id = dv.pid
WHERE p.deleted = 0
ORDER BY p.created DESC
LIMIT 0,10