Sql 导致干扰的已联接表
我有一个很大但有点简单的SQL查询。基本上,我的网站上的用户在不同类型的活动中建立了声誉,例如写评论、留下评论和向数据库添加条目。在大多数情况下,这些点存储在信誉良好的行动表中,我通过左键反复加入信誉良好的行动表来检索它们。这感觉很草率,但基本上是有效的 我遇到的问题是其中两个声誉“reviewer”和“community”。与其他的不同,它们不存储在声誉良好的\u actions表中。取而代之的是,它们的值是从投票表中派生出来的,我首先通过左键连接comments表来访问投票表。出于某种原因,加入评论表会导致我的所有其他声誉成倍增长。在一次试验中,“档案管理员”的名声本来应该是25岁,但当我加入评论时,它膨胀到10050岁 我是SQL的新手,我已经尝试了我所知道的(即,将GROUPBY子句应用于users.id),但我还没有任何运气。如能提供一些指导,将不胜感激Sql 导致干扰的已联接表,sql,join,Sql,Join,我有一个很大但有点简单的SQL查询。基本上,我的网站上的用户在不同类型的活动中建立了声誉,例如写评论、留下评论和向数据库添加条目。在大多数情况下,这些点存储在信誉良好的行动表中,我通过左键反复加入信誉良好的行动表来检索它们。这感觉很草率,但基本上是有效的 我遇到的问题是其中两个声誉“reviewer”和“community”。与其他的不同,它们不存储在声誉良好的\u actions表中。取而代之的是,它们的值是从投票表中派生出来的,我首先通过左键连接comments表来访问投票表。出于某种原因,
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
基本上,您需要进行两次单独的分组,并将结果合并。有一个技巧可以避免多次加入,如果您有许多其他可呕吐类型或声誉类型,可能不会更快
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
。如果您的表的结构与此不同,请告诉我。注释和/或投票中有多行与联接“其余”中的一行匹配。这将“乘以”结果行,并将其他聚合函数的结果与之相乘(如您已经注意到的)
最简单的解决方案是在单独的查询中获取SUM(reviewers.value)
和SUM(communities.value)
顺便说一句,如果有一个以上的
信誉良好的行为
行(同一信誉类型
)与同一用户
行匹配,你也会遇到同样的问题。我想最后应该有一个GROUP BY子句?很好。我已经添加了GROUPBY子句。谢谢您提供的好例子。这有点超出我的理解力,但我慢慢地理解了。在“Coalesce(v.replies 0)as replies”的末尾,我继续得到一个语法错误,我认为这是因为v.replies没有正确创建。我尝试过使用内部连接和左侧外部连接,但都没有效果。我认为问题出在最后一行,“v On u.id=v.user\u id”;评论可以。不幸的是,我不能在这里只做c.user\u id,因为注释超出了范围。(对吗?)有什么建议可以传达这些信息吗?我试图将ID包含在一个select中。@timothythehuman这是因为我错过了v.reples和0之间的逗号,修复了nowEgads,我自己应该能够捕捉到它。不过,谢谢你的帮助。我做了一系列测试,一切都正常。这是一个巨大的帮助,它向我展示了两种更好的编写查询的方法。再次感谢!