在忽略重复项的同时加入表

时间:2013-09-27 16:33:45

标签: mysql sql join left-join

所以,假设我有一个哈希/关系表,用于连接用户,用户可以加入的团队,以及团队参与的挑战(teams_users_challenges),以及存储所有用户输入数据的表在给定的挑战中(entry_data)。我想获得挑战中每个用户的平均分数(给定周内每天的平均值)。但是,用户可能会以某种方式错误地加入多个团队(这不应该发生,但有时会发生)。以下是获取特定用户得分的SQL查询:

SELECT tuc.user_id, SUM(ed.data_value) / 7 as value
FROM teams_users_challenges tuc
LEFT JOIN entry_data ed ON (
    tuc.user_id = ed.user_id AND
    ed.entry_date BETWEEN '2013-09-16' AND '2013-09-22'
)
WHERE tuc.challenge_id = ___
AND tuc.user_id = ___

如果用户错误地加入了多个团队,他将在teams_users_challenges中有多个条目,这实际上会复制检索到的数据。因此,如果一个用户在同一个挑战的3个不同的团队中,他将在teams_users_challenges中有3个条目,这将使他们的平均value乘以3,这要归功于LEFT JOIN它会自动接收所有记录,而不仅仅是一个记录。

我已尝试使用GROUP BY,但这似乎并未将数据仅限制为teams_users_challenges中的一个实例。有没有人想过如何限制查询只能在teams_users_challenges内收录一条记录?

ADDENDUM: teams_users_challenges中的列为team_iduser_idchallenge_id

2 个答案:

答案 0 :(得分:1)

如果这是一个新的空表,您可以表达您的“业务规则”,即用户每次挑战只能加入一个团队作为SQL中的unique约束:

alter table teams_users_challenges
add constraint oneUserPerTeamPerChallenge
unique (
  user_id
, team_id
, challenge_id
);

如果您无法更改表格,则需要按用户和团队进行分组,并从查询结果中的每个组中挑选一个挑战。也许只选择最新的挑战。

答案 1 :(得分:1)

我无法测试,但如果您无法像Y​​awar建议的那样清理数据,请尝试:

SELECT tuc.user_id, SUM(ed.data_value) / 7 as value
FROM entry_data ed
LEFT JOIN
(
select tuc.user_id, tuc.challenge_id from teams_users_challenges tuc group by tuc.user_id, tuc.challenge_id
) AS SINGLE_TEAM
 ON SINGLE_TEAM.user_id = ed.user_id AND
    ed.entry_date BETWEEN '2013-09-16' AND '2013-09-22'
WHERE tuc.challenge_id = ___
AND tuc.user_id = ___