【问题标题】:MySQL query broke after adding join添加连接后 MySQL 查询中断
【发布时间】:2018-09-20 18:41:16
【问题描述】:

我有一个查询,它为我的 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

【问题讨论】:

  • 因为 cmets 可能在您的用户/页表中包含许多记录,因此您的计数会针对 cme​​ts 表中的每条记录与您之前的记录相加。尝试在 where 子句中仅使用一个页面/用户进行测试,您将能够看到它
  • " 因为 cmets 中可能有很多记录到您的用户/页表中的记录,所以您的计数将被添加到 cmets 表中的每条记录与您之前的记录相比“好吧@ COUNT 中的 987654322@ 应该抵消(通常)@Brad .. 所以他可以这样做 COUNT(DISTINCT CASE WHEN votelog.vote !="" THEN 1 END) AS 'totalvotes',.. 但最好使用像 Gordon Linoff's answer 这样的交付表(子查询)方法
  • 计数不是他所说的问题,而是他有问题的赞成/反对票,而且他没有考虑在逻辑的那部分添加的 cmets。跨度>
  • 注意我说的@Brad "@Brad .. "所以他可以做 COUNT(DISTINCT CASE WHEN votelog.vote !="" THEN 1 END) AS 'totalvotes',"
  • 对不起,我在您完成评论之前回复了您指出的详细信息。

标签: mysql sql database content-management-system


【解决方案1】:

看来你决定加入表comments只是为了计算有多少 cmets

但是通过这样做,您现在会生成多行,每条评论一行,这会消除所有其他计数。

我建议使用标量子查询来计算 cmets,并删除连接。比如:

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

【讨论】:

  • 我收到一条错误消息,提示“子查询返回多于一行”
  • 我的错。我忘记了第二行中的COUNT()。固定。
  • 哇,效果很好。我要研究它。非常感谢!
【解决方案2】:

您有多个评论。所以,在加入之前聚合:

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;

注意事项:

  • 表别名使查询更易于编写和阅读。
  • GROUP BY 中包含所有非聚合列是一种很好的做法(并且最新版本的 MySQL 倾向于强制执行此操作)。
  • 我假设选票是数字。将它们与数字而非字符串进行比较。
  • MySQL 有一个很好的简写方式来计算布尔表达式为真的次数。

【讨论】:

  • 也许是因为所有的别名,但我很困惑。我喜欢你使用 sum 函数的方式。你可以在没有所有别名的情况下发布它,或者只是解释我应该如何定义它们。它不运行,不确定它是否应该这样运行。
  • @badcarbine 。 . .别名应该使查询更容易写和读,而不是更难。
猜你喜欢
  • 2013-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-07
  • 2021-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多