【问题标题】:Selecting posts, user details and votes from 3 MySQL tables从 3 个 MySQL 表中选择帖子、用户详细信息和投票
【发布时间】:2014-04-07 01:43:34
【问题描述】:

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

发布表,包含 id、uid(用户 id)、内容等和

vote 表,带有 id、uid、pid(post id)、vote(ENUM:'1' 和 '-1')。

Vote 表的投票栏中,1 代表赞成票,-1 代表反对票。

我希望选择十个包含用户详细信息且没有赞成票和反对票的帖子。我用下表试过了,但它不起作用。它为某些 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           |
+----+-----+--------+----------+---------+-----------+-----------+-------------+

第一行给出了 upvoteIdsupvotes 的重复 id 为 2。这里,upvotes 应该是 1,因为 id 为 19 的帖子只有 1 个 upvote。看看下面的 votes 表格:

+----+-----+-----+------+
| 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 |
+----+-----+--------+

【问题讨论】:

  • 你能添加一个 SQLFiddle 吗?
  • 其他表的数据能不能也贴一下
  • 添加了post表数据。用户表具有您所期望的一般 id、用户名、电子邮件字段。
  • 明白。如何正确处理?
  • post表的uid列有什么意义?那是帖子的作者吗?

标签: mysql left-join


【解决方案1】:

我始终建议从包含最终需要分组的数据的表开始,在本例中为 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

【讨论】:

  • 您的查询非常合理。它不仅按预期工作,而且解释得很漂亮。非常感谢您抽出时间来帮助和节省我的时间。
猜你喜欢
  • 2012-01-12
  • 1970-01-01
  • 2015-03-04
  • 1970-01-01
  • 2021-04-16
  • 2019-04-23
  • 2020-09-28
  • 1970-01-01
  • 2019-11-29
相关资源
最近更新 更多