2009-03-04 166 views
10

我必须按照用户活动的日,周,月和年收集统计信息。我是DB设计阶段,我想正确地完成这个阶段,因为它会让我的编码生活更轻松。用于按日,周,月,年保存统计信息的数据库结构

我所要做的只是简单地在每次活动发生时在数据库中将字段中的值增加1。那么我可以每天,每周,每月和每年提出日期。我的数据库应该如何构建?如果对大多数人来说这是一个简单的问题,请道歉如果这种结构可以扩展以便可以按照其他类别进行细分,那也是很好的。

有问题的是每个月都是由多个日子组成的,这些日子是每个日历年都会改变的。

谢谢大家的帮助或指导。

其他信息:Linux的机器,利用PHP和MySQL

回答

19

,而不是更新,一周每天计数等只是行插入表中每一个活动发生这样的时刻:

insert into activities (activity_date, activity_info) 
values (CURRENT_TIMESTAMP, 'whatever'); 

现在,您的报告中都像很简单:

select count(*) from activities 
where activity_date between '2008-01-01' and '2008-01-07'; 

select YEARWEEK(`activity_date`) as theweek, count(*) 
group by theweek 
+1

如果例如记录的活动每次都发生时,这个表是否会变得非常大页面被加载了一个网站,并且有很多用户在这个网站上持有账户? – Abs 2009-03-04 14:21:39

+1

是的。这是你应该从最初的设计开始。优化可能会晚些时候。 – thomasrutter 2009-03-04 14:29:33

4

您可以使用集合函数将记录添加到表格中并将其添加到SELECT中。

如果由于某种原因,你需要保留汇总统计,你可以使用:

CREATE TABLE aggregates (type VARCHAR(20), part VARCHAR(10) NOT NULL PRIMARY KEY, activity INT) 

INSERT INTO aggregates (type, part, activity) 
VALUES ('year', SUBSTRING(SYSDATE(), 1, 4), 1) 
ON DUPLICATE KEY UPDATE activity = activity + 1 

INSERT INTO aggregates (type, part, activity) 
VALUES ('month', SUBSTRING(SYSDATE(), 1, 7), 1) 
ON DUPLICATE KEY UPDATE activity = activity + 1 

INSERT INTO aggregates (type, part, activity) 
VALUES ('day', SUBSTRING(SYSDATE(), 1, 10), 1) 
ON DUPLICATE KEY UPDATE activity = activity + 1 

这将自动更新现有行并插入不存在的必要时。

3
  1. 事件表:id,activity id,datetime,userid。
  2. 表的用户:ID,用户名等活动
  3. 表:ID,活动名称等

只需输入一行新的事件时事件发生。然后你可以分析事件,但操纵时间,日期,用户,活动等。

2

首先,你可能会想象一个单一的表,因为这将是最规范化的形式。该表格只会包含您收到的每个命中的条目,每行包含该命中的日期/时间。

现在,通过这种方式,为了获得每小时,每天,每周等的统计数据,查询很简单,但是您的数据库必须执行一些相当繁重的查询工作。特别是,执行求和,计数或平均值的查询将需要获取所有相关的行。

您可以通过在第二个表中预先计算所需的计数并确保将该表定期与第一个表同步来解决此问题。问题是,您将负责让自己的缓存保持同步。

这可能会涉及每个小时做一行。如果您每天只能获取最多24行,那么查询一天或一个月的速度仍然会更快。

您的其他建议是从一开始就将它聚合起来,绝不会将每一个命中行存储为一行。像以前一样,你可能会这样做,每小时一排。每一击都会使有关小时数增加1。你只能将数据放在一个位置,而且它已经很好地总结了。

我建议小时而不是白天的原因是,这仍然可以让您选择支持多个时区。如果您的粒度仅限于当天,那么您没有该选项。

1

托尼·安德鲁斯的答案是最简单的,但是雪花结构有时用于数据仓库应用程序:一个表包含所有活动,另一个表示每天的活动,另一个表示每月的活动,第三个表示活动年。利用这种结构,可以非常有效地计算任意两个日期之间的活动。 https://en.wikipedia.org/wiki/Snowflake_schema

1

使用星型模式设计。 (或者可能是雪花设计)。

Star-Schema Design

你最终会做插入到事实表中的每个新的活动。见托尼的建议。

您至少需要两个维度表,一个用于用户,另一个用于时间范围。可能会有活动类型的维度,甚至可能是位置。这取决于你想要对数据做什么。

您的问题涉及时间范围的维度表。我们称之为“年历”。选择一个粒度。让我们说一天。年历每天会有一行。主键可以是日期。您的事实表应该包含此主键作为外键,以便更轻松地进行联接。 (无论您是否将其声明为外键,只影响更新过程中的参照完整性。)

在您可以想到的每个报告周期的年鉴中包含列。周,月,季,年等。甚至可以包括与公司自己的日历相关的报告期。

这是一篇比较ER和DM的文章。我很不寻常,因为我喜欢这两种方法,为适当的任务选择合适的方法。

http://www.dbmsmag.com/9510d05.html

0

你的问题涉及到时间帧维度表。我们称之为“年历”。选择一个粒度。让我们说一天。年历每天会有一行。主键可以是日期。您的事实表应该包含此主键作为外键,以便更轻松地进行联接。 (无论你是否声明它是一个外键,只会影响更新过程中的参照完整性。)

相关问题