MySQL 添加联接后查询中断
MySQL query broke after adding join
我有一个查询,它在我的 CMS 中循环加载数据以显示帖子。在我离开加入评论栏之前,投票栏中的一切都运行良好。评论显示正常,但总票数、赞成票和反对票数严重偏差。如果您需要查看表格,请告诉我。
SELECT
count(DISTINCT comment.comment ) AS Comment,
idea.dateofcreation AS timestamp,
idea.userId AS userId,
idea.id AS ID,
idea.text AS Idea,
page.permalink AS Permalink,
user.name AS Username,
COUNT(CASE WHEN votelog.vote !="" THEN 1 END) AS 'totalvotes',
COUNT(CASE WHEN votelog.vote = '1' THEN 1 END) AS 'upvote',
COUNT(CASE WHEN votelog.vote = '-1' THEN 1 END) AS 'downvote'
FROM idea
LEFT JOIN votelog ON idea.id = votelog.ideaid
LEFT JOIN user ON idea.userId = user.id
LEFT JOIN page ON idea.id = page.ideaid
LEFT join comment ON comment.ideaid = idea.id
GROUP BY idea.id
ORDER BY totalvotes DESC
您有不止一条评论。所以,在加入之前聚合:
SELECT c.num_comments,
i.dateofcreation AS timestamp, i.userId AS userId, i.id AS ID, i.text AS Idea,
p.permalink AS Permalink, p.name AS Username,
SUM( vl.vote <> '' ) AS totalvotes,
SUM( vl.vote = 1 ) AS upvote,
SUM( vl.vote = -1 ) AS downvote
FROM idea i LEFT JOIN
votelog vl
ON i.id = vl.ideaid LEFT JOIN
user u
ON i.userId = u.id LEFT JOIN
page p
ON i.id = p.ideaid LEFT JOIN
(SELECT c.ideaid, COUNT(*) as num_comments
FROM comment c
GROUP BY c.ideaid
) c
ON c.ideaid = i.id
GROUP BY c.num_comments,
i.dateofcreation i.userId, i.id, i.text,
p.permalink, p.name
ORDER BY totalvotes DESC;
备注:
- Table 别名使查询更易于编写和阅读。
- 在
GROUP BY
中包含所有非聚合列是一个很好的做法(MySQL 的较新版本倾向于强制执行此操作)。
- 我假设选票是数字。将它们与数字进行比较,而不是与字符串进行比较。
- MySQL 有一个很好的 shorthand 用于计算布尔表达式为真的次数。
看来您决定加入 table comments
只是为了计算有多少评论。
但是通过这样做,您现在会生成多行,每个评论一行,这会减少所有其他计数。
我建议使用标量子查询来计算评论数,并删除连接。类似于:
SELECT
(select count(DISTINCT comment) from comment c where c.ideaid = idea.id) AS Comment,
idea.dateofcreation AS timestamp,
idea.userId AS userId,
idea.id AS ID,
idea.text AS Idea,
page.permalink AS Permalink,
user.name AS Username,
COUNT(CASE WHEN votelog.vote !="" THEN 1 END) AS 'totalvotes',
COUNT(CASE WHEN votelog.vote = '1' THEN 1 END) AS 'upvote',
COUNT(CASE WHEN votelog.vote = '-1' THEN 1 END) AS 'downvote'
FROM idea
LEFT JOIN votelog ON idea.id = votelog.ideaid
LEFT JOIN user ON idea.userId = user.id
LEFT JOIN page ON idea.id = page.ideaid
GROUP BY idea.id
ORDER BY totalvotes DESC
我有一个查询,它在我的 CMS 中循环加载数据以显示帖子。在我离开加入评论栏之前,投票栏中的一切都运行良好。评论显示正常,但总票数、赞成票和反对票数严重偏差。如果您需要查看表格,请告诉我。
SELECT
count(DISTINCT comment.comment ) AS Comment,
idea.dateofcreation AS timestamp,
idea.userId AS userId,
idea.id AS ID,
idea.text AS Idea,
page.permalink AS Permalink,
user.name AS Username,
COUNT(CASE WHEN votelog.vote !="" THEN 1 END) AS 'totalvotes',
COUNT(CASE WHEN votelog.vote = '1' THEN 1 END) AS 'upvote',
COUNT(CASE WHEN votelog.vote = '-1' THEN 1 END) AS 'downvote'
FROM idea
LEFT JOIN votelog ON idea.id = votelog.ideaid
LEFT JOIN user ON idea.userId = user.id
LEFT JOIN page ON idea.id = page.ideaid
LEFT join comment ON comment.ideaid = idea.id
GROUP BY idea.id
ORDER BY totalvotes DESC
您有不止一条评论。所以,在加入之前聚合:
SELECT c.num_comments,
i.dateofcreation AS timestamp, i.userId AS userId, i.id AS ID, i.text AS Idea,
p.permalink AS Permalink, p.name AS Username,
SUM( vl.vote <> '' ) AS totalvotes,
SUM( vl.vote = 1 ) AS upvote,
SUM( vl.vote = -1 ) AS downvote
FROM idea i LEFT JOIN
votelog vl
ON i.id = vl.ideaid LEFT JOIN
user u
ON i.userId = u.id LEFT JOIN
page p
ON i.id = p.ideaid LEFT JOIN
(SELECT c.ideaid, COUNT(*) as num_comments
FROM comment c
GROUP BY c.ideaid
) c
ON c.ideaid = i.id
GROUP BY c.num_comments,
i.dateofcreation i.userId, i.id, i.text,
p.permalink, p.name
ORDER BY totalvotes DESC;
备注:
- Table 别名使查询更易于编写和阅读。
- 在
GROUP BY
中包含所有非聚合列是一个很好的做法(MySQL 的较新版本倾向于强制执行此操作)。 - 我假设选票是数字。将它们与数字进行比较,而不是与字符串进行比较。
- MySQL 有一个很好的 shorthand 用于计算布尔表达式为真的次数。
看来您决定加入 table comments
只是为了计算有多少评论。
但是通过这样做,您现在会生成多行,每个评论一行,这会减少所有其他计数。
我建议使用标量子查询来计算评论数,并删除连接。类似于:
SELECT
(select count(DISTINCT comment) from comment c where c.ideaid = idea.id) AS Comment,
idea.dateofcreation AS timestamp,
idea.userId AS userId,
idea.id AS ID,
idea.text AS Idea,
page.permalink AS Permalink,
user.name AS Username,
COUNT(CASE WHEN votelog.vote !="" THEN 1 END) AS 'totalvotes',
COUNT(CASE WHEN votelog.vote = '1' THEN 1 END) AS 'upvote',
COUNT(CASE WHEN votelog.vote = '-1' THEN 1 END) AS 'downvote'
FROM idea
LEFT JOIN votelog ON idea.id = votelog.ideaid
LEFT JOIN user ON idea.userId = user.id
LEFT JOIN page ON idea.id = page.ideaid
GROUP BY idea.id
ORDER BY totalvotes DESC