为简单起见,我将简要介绍一下我想要实现的目标:
ID | Name
--------------------
1 | John
2 | Mike
3 | Sam
ID | planID
--------------------
1 | 1
1 | 2
1 | 1
2 | 2
2 | 3
3 | 2
3 | 1
planID | Cost
--------------------
1 | 5
2 | 10
3 | 12
当我运行查询时,我想返回按成员分组的所有成员选择的总和。然而,我面临的问题(例如表2数据)是某些成员可能在系统内错误地重复信息。虽然我们尽最大努力预先过滤这些数据,但有时它会滑过裂缝,所以当我对系统进行必要的调用以获取信息时,我也想过滤这些数据。
结果应该显示:
ID | Name | Total_Cost
-----------------------------
1 | John | 15
2 | Mike | 22
3 | Sam | 15
但是将约翰作为20美元,因为他错误地插入了两次计划ID#1。
我的查询目前是:
SELECT
sq.ID, sq.name, SUM(sq.premium) AS total_cost
FROM
(
SELECT
m.id, m.name, g.premium
FROM members m
INNER JOIN member_selections s USING(ID)
INNER JOIN selection_details g USING(planid)
) sq group by sq.agent
添加DISTINCT s.planID会错误地过滤结果,因为它只显示出售的单个PlanID 1(即使成员1和3购买了它)。
感谢任何帮助。
我还忘了提到另一张表,即代理人表(将计划卖给会员的代理人)。
最后一组by语句分组代理ID销售的所有项目(将最终结果转换为单行)。
答案 0 :(得分:2)
也许最简单的解决方案是在member_selections表上放置一个唯一的复合键:
alter table member_selections add unique key ms_key (ID, planID);
这将阻止添加任何记录,其中ID / planID的唯一组合已存在于表中的其他位置。那只允许一个(1,1)
评论后续:
刚刚看到你对'alter ignore ...'的评论。这工作正常,但你仍然会留下表中的重复副本。我建议做一个唯一的密钥,然后手动清理表。我在评论中提出的查询应该找到所有重复项,然后您可以手动清除。一旦表格干净,就不需要复制处理版本的查询。
答案 1 :(得分:0)
使用UNIQUE键防止意外重复输入。这将消除源头的问题,而不是在它开始出现症状时。它还使后续查询更容易,因为您可以依赖于拥有一致的数据库。
答案 2 :(得分:0)
怎么样:
SELECT
sq.ID, sq.name, SUM(sq.premium) AS total_cost
FROM
(
SELECT
m.id, m.name, g.premium
FROM members m
INNER JOIN
(select distinct ID, PlanID from member_selections) s
USING(ID)
INNER JOIN selection_details g USING(planid)
) sq group by sq.agent
顺便说一下,有没有理由你在member_selections上没有主键,这会阻止这些副本首先发生?
答案 3 :(得分:0)
您可以将group by子句添加到内部查询中,该查询按所有三列进行分组,基本上只返回唯一的行。 (我还将'premium'更改为'cost'以匹配您的示例表,并删除了代理程序部分)
SELECT
sq.ID,
sq.name,
SUM(sq.Cost) AS total_cost
FROM
(
SELECT
m.id,
m.name,
g.Cost
FROM
members m
INNER JOIN member_selections s USING(ID)
INNER JOIN selection_details g USING(planid)
GROUP BY
m.ID,
m.NAME,
g.Cost
) sq
group by
sq.ID,
sq.NAME