如何按日期分组,但在select语句中使用日期作为条件?

时间:2015-02-14 19:30:36

标签: php mysql sql datetime

我真的不确定如何标题这个问题,很抱歉......

我有一个网站,用户可以观看"产品。当他们开始观看产品时,会在product_tracking中插入一行,如下所示:

+-----------------------+------------+------+-----+---------+----------------+
| Field                 | Type       | Null | Key | Default | Extra          |
+-----------------------+------------+------+-----+---------+----------------+
| id                    | bigint(11) | NO   | PRI | NULL    | auto_increment |
| u_id                  | int(11)    | NO   | MUL | NULL    |                |
| p_id                  | bigint(11) | NO   | MUL | NULL    |                |
| date_started_tracking | datetime   | NO   |     | NULL    |                |
| date_stopped_tracking | datetime   | YES  |     | NULL    |                |
+-----------------------+------------+------+-----+---------+----------------+

用户开始观看插入行时date_started_tracking插入产品的日期时间,默认情况下date_stopped_trackingnull。当用户停止观看产品时,date_stopped_tracking将使用当前日期时间进行更新。

我希望在我的网站上有一个图表,显示随时间推移跟踪的产品数量。像这样:

# tracks
|                       __/
|               ___    /      
|              /   \__/     
|             /       
|            /
|       ____/
|      /
|  ___/
| /
|/___________________________ date (grouped by day, week, or month)

我不知道如何编写查询来检索制作图表所需的信息。

难以理解的是,我希望按天,周或月对行进行分组,但如果date_started_tracking为< =分组日期,则只包含组中的行date_stopped_trackingnull >分组日期(即选择显示在该日期被跟踪的产品的行)。

换句话说,对于每天,每周或每月(取决于所需的粒度),应返回当时用户正在观看的产品数量。


我尝试解决方案

我提出的唯一想法是创建一个日期表,然后编写一个查询,例如:

SELECT WEEK(d.date) as week, 
       (SELECT COUNT(pt.id) 
        FROM product_tracking pt
        WHERE pt.date_started_tracking <= d.date AND (pt.date_stopped_tracking IS NULL OR pt.date_stopped_tracking > d.date)
        ) as numWatches
FROM dates d
GROUP BY week
ORDER BY week ASC

我认为这样可行,但需要创建一个日期表,这似乎有点迟钝。

有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

您的方法有效,但无法很好地扩展。另一种方法是使用累积和的变量逐日跟踪跟踪。这看起来像:

select dte, sum(inc) as net,
       (@sum := @sum + sum(inc)) as total_for_day
from ((select date_start_tracking as dte, count(*) as inc
       from product_tracking
       group by date_start_tracking
      ) union all
      (select date_stopped_tracking, - count(*)
       from product_tracking
       where date_stopped_tracking is not null
       group by date_stopped_tracking
      )
     ) pt cross join
     (select @sum := 0) vars
group by dte
order by dte;

这是解决方案的概要。对于您的数据,您可能需要一个超过停止日期 - 取决于该产品是否在当天计算。

然后,您可以将此查询用作子查询,以便在您喜欢的任何时间段进行聚合。