根本不存储点。只需对此视图进行查询即可。这样一来,面对任意改变,它就会很健壮。
create view UserPoints
as
select
created_by_id as user_id,
'STORE' as action_type,
store_id as action_id,
(select points from action_points where action_desc='create store') as points
from store
union
select
user_id,
'ANSWER' as action_type,
question_id as action_id,
(select points from action_points where action_desc='answer question') as points
from answer
union
select
referred_by_id as user_id,
'REFERRAL' as action_type,
referred_id as action_id,
(select points from action_points where action_desc='referral') as points
from referral
编辑补充:
这遵循了正常的数据库设计原则。所有数据库规范化都可以归结为:不重复数据。
包含点表基本上只是重复其余数据库已包含的信息。因此,应该省略。考虑到维护数据一致性所必须达到的长度,这一点已经很清楚。不用担心这些问题,如果推荐是归功于Alice,但是后来确定Bob应该获得这笔贷款,则需要更改单个表格中单个行中的单个字段。如果包含点表,那么它也必须以某种方式更新。如果积分总结被存储,那么上帝可能会怜悯你的数据库。
而不是存储点,可以使用视图或存储过程来代替,然后当数据更改时自动调整点系统。
在这种情况下,我认为视图对于存储过程是可以推出的,因为有很多方法可能需要分析点数据,并且这提供了最大的灵活性,并且它为优化器提供了最佳机会确定最佳路径。
您可以从视图中选择user_id或action_type或总结点列以获取用户或所有用户的总计。看看你可以拥有的乐趣,它几乎免费!
select
sum(up.points) as total_points,
up.user_id,
u.user_name
from
UserPoints up
join user u on up.user_id = u.user_id
group by
user_id,
user_name
order by
total_points desc
谢谢杰弗里 - 我没有想到这种方法 – Gublooo 2010-02-22 17:08:20
@Jeffrey,非常有趣的方法确实。看到这是一个非常古老的线程。只是好奇,这种方法在一个系统中能够很好地扩展,比如像SO一样大?这个视图可能非常复杂,数据集可能非常大。 – 2016-03-09 16:19:22