我有一个很大但有点简单的SQL查询。基本上,我网站上的用户为不同类型的活动开发声誉,例如撰写评论,留下评论以及向数据库添加条目。在大多数情况下,这些点存储在reputable_actions表中,我通过LEFT重复连接reputable_actions表来检索它们。这感觉很草率,但它主要起作用。
我遇到的问题是两个声誉,“评论家”和“社区”。与其他人不同,它们不存储在reputable_actions表中。相反,它们的值来自投票表,我首先通过LEFT JOINing comments表访问它。出于某种原因,加入评论表会导致我的所有其他声誉呈指数级增长。在一次试验中,“档案保管员”的声誉被认为是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
答案 0 :(得分: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
Example (with no data)。如果您的表格结构与此不同,请与我们联系。
答案 1 :(得分:1)
comments
和/或votes
中的多个行与联接的“其余”中的一行行匹配。这会将所得行“相乘”并将其他聚合函数的结果与其相乘(如您所知)。
最简单的解决方案是将SUM(reviewers.value)
和SUM(communities.value)
放在单独的查询中。
reputable_actions
行(相同的reputation_type
)匹配相同的users
行,您会遇到同样的问题。