我有一个非常简单的SQL要求,但是由于遇到了性能问题,我想知道下面场景的“最佳实践”是什么。
我有一个团队列表,每周/每周这些团队支付游戏费。如果团队没有支付,那么他们将有一个未结余额。所有团队付款都会进入付款表,这个表越来越大。返回具有当前余额的团队列表的最佳做法是什么?
我现在拥有的内容:
Select teams.*, (Select SUM(amount) from payments p where p.TeamID=teams.TeamID) as teambalance
from (select TeamID, TeamName from Teams) teams
答案 0 :(得分:2)
我已经考虑了很多,并且认为“不要两次存储相同信息”的经典建议在这里是错误的,或者至少被误解了。
考虑银行必须如何做到这一点。显然,当您想知道自己的当前余额并且您已经成为客户20年时,他们不会将20年的帐户活动加起来以找到您当前的余额。鉴于此,我认为有两种方法可以处理它:
只要表现合适,您可以继续添加。但它可能不是最佳的。
您当前的查询没问题,但不需要teams
派生表。除非你使用MySQL,否则DBMS不需要这种“帮助” - 尽管MySQL实际上可能会受到它的伤害。
答案 1 :(得分:1)
select teamId,teamName,sum(amount)
from teams t join payments p on t.teamId = p.teamId
group by t.teamId, t.teamName
答案 2 :(得分:0)
我使用了两种方法来完成此任务 - 一种是您当前使用的方法。另一种是使用交叉申请。
我更喜欢你现在的方法 -
答案 3 :(得分:0)
这可能比在SELECT子句(或连接)中使用子查询更快:
select teams.TeamID, teams.teamName, team_balances.teambalance
from teams
join ( select TeamID, sum(amount) teambalance
from payments
group by TeamID
) team_balances
on team_balances.TeamID = teams.TeamID;
这将按顺序扫描支付表一次,而不是进行N次索引扫描(每个团队一次)。
<强>反规范化强>
另一个选择是创建向teams表添加“outstanding_balance”列。
在付款表上创建触发器。在触发器中,分别根据TeamID和发票/付款金额增加或减少团队中的outstanding_balance列。
根据您的RDBMS,您还可以使用物化视图。这类似于触发方法,除了每个团队的余额将存储在不同的表中。