0

我有一个大但有些简单的 SQL 查询。基本上,我网站上的用户会为不同类型的活动建立声誉,例如撰写评论、发表评论以及向我们的数据库添加条目。在大多数情况下,这些点存储在 reputable_actions 表中,我通过重复左连接 reputable_actions 表来检索它们。这感觉很草率,但它主要是有效的。

我遇到的问题是两个声誉,“审稿人”和“社区”。与其他人不同,它们不存储在 reputable_actions 表中。相反,它们的值来自投票表,我首先通过左连接评论表来访问该表。出于某种原因,加入评论表会导致我所有其他的声誉成倍增加。在一次试验中,“档案管理员”的声誉应该是 25,但当我加入评论时,它飙升至 10050。

我是 SQL 的新手,我已经尝试了我所知道的(即,将 GROUP BY 子句应用于 users.id),但我还没有运气。一些指导将不胜感激。

SELECT users.*,
  SUM(COALESCE(reviewers.value, 0)) as reviewer,
  SUM(COALESCE(communities.value,0)) as community,
  SUM(COALESCE(developers.value,0)) as developer,
  SUM(COALESCE(moderators.value,0)) as moderator,
  SUM(COALESCE(marketers.value,0)) as marketer,
  SUM(COALESCE(archivists.value,0)) as archivist,
  SUM(COALESCE(karmas.value,0)) as karma
FROM `users`
LEFT JOIN comments AS impressions
  ON impressions.user_id = users.id
  AND impressions.type = 'impression'
LEFT JOIN comments AS replies
  ON replies.user_id = users.id
  AND replies.type = 'reply'
LEFT JOIN votes AS reviewers
  ON reviewers.voteable_type = 'impression'
  AND reviewers.voteable_id = impressions.id
LEFT JOIN votes AS communities
  ON communities.voteable_type = 'reply'
  AND communities.voteable_id = replies.id
LEFT JOIN reputable_actions AS developers
  ON developers.reputation_type = 'developer'
  AND developers.user_id = users.id
LEFT JOIN reputable_actions AS moderators
  ON moderators.reputation_type = 'moderator'
  AND moderators.user_id = users.id
LEFT JOIN reputable_actions AS marketers
  ON marketers.reputation_type = 'marketer'
  AND marketers.user_id = users.id
LEFT JOIN reputable_actions AS archivists
  ON archivists.reputation_type = 'archivist'
  AND archivists.user_id = users.id
LEFT JOIN reputable_actions AS karmas
  ON karmas.reputation_type = 'karma'
  AND karmas.user_id = users.id
GROUP BY users.id
4

2 回答 2

1

基本上你需要做两个单独的分组,并结合结果。有一个技巧可以避免多次加入,如果您有许多其他可投票类型或声誉类型,它可能不会更快。

Select
  u.*,
  Coalesce(r.developer, 0) as developer,
  Coalesce(r.moderator, 0) as moderator,
  Coalesce(r.marketer, 0) as marketer,
  Coalesce(r.archivist, 0) as archivist,
  Coalesce(r.karma, 0) as karma,
  Coalesce(v.impressions, 0) as impressions,
  Coalesce(v.replies, 0) as replies
From
  users u
    Left Outer Join (
    Select
      user_id,
      Sum(Case When reputation_type = 'developer' Then value Else 0 End) as developer,
      Sum(Case When reputation_type = 'moderator' Then value Else 0 End) as moderator,
      Sum(Case When reputation_type = 'marketer' Then value Else 0 End) as marketer,
      Sum(Case When reputation_type = 'archivist' Then value Else 0 End) as archivist,
      Sum(Case When reputation_type = 'karma' Then value Else 0 End) as karma
    From
      reputable_actions
    Group By
      user_id
  ) r On u.id = r.user_id
    Left Outer Join (
    Select
      c.user_id,
      Sum(Case When c.type = 'impression' Then v.value Else 0 End) as impressions,
      Sum(Case When c.type = 'reply' Then v.value Else 0 End) as replies
    From
      comments c
        inner join -- maybe left outer?
      votes v
        on v.voteable_type = c.type And v.voteable_id = c.id
    Group By
      user_id
  ) v On u.id = v.user_id

示例(没有数据)。如果您的表格结构与此不同,请告诉我。

于 2012-12-01T00:42:29.823 回答
1

有多comments和/或与连接的“其余”中的一行匹配votes。这将结果行“相乘”并将其他聚合函数的结果与它相乘(正如您已经指出的那样)。

最简单的解决方案是在单独的查询中获取SUM(reviewers.value)and 。SUM(communities.value)

顺便说一句,如果有不止reputable_actions一行(相同的reputation_type)匹配同一users行,您将遇到同样的问题。

于 2012-12-01T00:45:50.233 回答