简体   繁体   English

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

[英]How to group by date, but use the date as a condition in the select statement?

I'm really not sure how to title this question, so sorry about that.. 我真的不确定如何为这个问题加上标题,对此感到抱歉。

I have a site where users can "watch" products. 我有一个网站,用户可以在其中“观看”产品。 When they start watching a product, a row is inserted into product_tracking , which looks like this: 当他们开始观看产品时,会在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    |                |
+-----------------------+------------+------+-----+---------+----------------+

The datetime the user starts watching the product is inserted into date_started_tracking when the row is inserted, and date_stopped_tracking is null by default. 插入date_started_tracking ,用户开始观看产品的日期时间将插入date_started_tracking ,并且date_stopped_tracking默认为null When the user stops watching a product, date_stopped_tracking is updated with the current datetime. 当用户停止观看产品时, date_stopped_tracking会更新为当前日期时间。

I want to have a chart on my site showing the number of products being tracked over time. 我想在我的网站上有一张图表,显示随着时间的推移所跟踪的产品数量。 Something like this: 像这样:

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

I don't know how to write a query to retrieve the information required to make the chart. 我不知道如何编写查询来检索制作图表所需的信息。

What makes it difficult is that I want to group rows by day, week, or month, but only include rows in a group if date_started_tracking is <= the grouping date and date_stopped_tracking is null or > the grouping date (ie select rows showing products being tracked at that date). 很难做到的是,我想按天,周或月对行进行分组,但仅在date_started_tracking为<=分组日期 date_stopped_trackingnull >分组日期的情况下才将行包括在组中(即,选择显示产品行的行)在该日期跟踪)。

In other words, for each day, week, or month (depending on the desired granularity), the number of products being watched by users at that time should be returned. 换句话说,对于每天,每周或每月(取决于所需的粒度),应返回当时用户正在观看的产品数量。


My attempt at a solution 我的解决方案

The only idea I've come up with is creating a table of dates and then writing a query such as: 我想到的唯一想法是创建一个日期表,然后编写一个查询,例如:

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

I think this will work, but it requires creating a table of dates, which seems kind of retarded. 我认为这会起作用,但是它需要创建一个日期表,这似乎有点迟钝。

Is there a better way? 有没有更好的办法?

Your method works, but it won't scale very well. 您的方法有效,但扩展性不佳。 An alternative approach is to keep track of the tracking day-by-day using variables for the cumulative sums. 一种替代方法是使用变量作为累积总和来跟踪跟踪。 This looks like: 看起来像:

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;

This is an outline of a solution. 这是解决方案的概述。 For your data, you might want one more than the stop date -- depending on whether or not the product is counted on that day. 对于您的数据,您可能需要比停止日期多一个-取决于当天是否计算了产品。

You can then use this query as a subquery to aggregate for whatever period you like. 然后,您可以将此查询用作子查询,以汇总所需的任何时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM