mySQL,按日期分组数据

标签 mysql date grouping

您好:SO 上似乎已经有很多关于这个问题的变体,但我无法根据我的需要调整其中的任何一个(无论如何都不是可行的方式)。

我有一个这样的表:

CREATE TABLE `AdServing`
(
  `imgID`           int UNSIGNED NOT NULL,
  `ServedTimeStamp` timestamp NOT NULL,
  `UserID`          int(10) UNSIGNED NOT NULL,
  `ServedIP`        VARBINARY(16) NULL,
  `Clicked`         Boolean NULL,
)

一些示例数据:

1   2015-08-04 14:59:48     1   192.168.0.4     1
1   2015-08-14 23:06:25     1   192.168.0.3     1
1   2015-08-16 15:00:09     1   192.168.0.3     1
1   2015-08-16 15:01:15     1   192.168.0.3     1
1   2015-08-16 15:01:43     1   192.168.0.3     1
1   2015-08-17 15:00:51     1   192.168.0.4     1
2   2015-07-26 17:55:21     1   192.168.0.2     0
3   2015-07-26 17:57:15     1   192.168.0.3     1
4   2015-07-26 17:57:15     1   192.168.0.4     1

我想创建一个图表,显示随时间推移转换的广告数量 - 从首次展示之日到最近一次展示之日。 像这样:

Chart

对于某些用户来说,这可能只有一周。对于其他人来说,可能需要 4 或 5 个月。对于另一个用户,这可能跨越一两年的时间段。

我认为无论时间段如何,图表沿时间轴可能会有 6 或 7 个数据点 - 因此对于只有一周数据的用户来说间隔可能是 1 天,或者对于有一周数据的用户来说间隔可能是 1 周几个月的数据......我不确定确定这一点的最佳策略 - 一个只有一个月数据的用户怎么样,例如,你如何将日子分成六/七组以某种方式这有意义吗?

但目前的主要问题是查询数据库以将表值提取到这些分组中。我想得到的是这样的:

DateGrouping  |  Servings
-------------------------
1             |  2
2             |  5
3             |  3
4             |  7
5             |  2
6             |  4
7             |  3

...其中“DateGrouping”将是适合当前用户数据的任何时间间隔,即对于一周的值,1-7 将代表一天。 “服务”将是每个时间间隔转换的广告数量。同样,这里假设每个时间间隔是一天,那就是每个记录的 24 小时内转换的广告数量(可能连续也可能不连续)。

我试图根据这个 SO 答案调整查询:https://stackoverflow.com/a/30335592/2577646

然后想出了这个:

SELECT x.DateRange, COALESCE(TotalWithinRange, 0) AS TotalWithinRange
FROM (
  SELECT '1' AS DateRange 
  UNION SELECT '2'
  UNION SELECT '3'
  UNION SELECT '4'
  UNION SELECT '5'
  UNION SELECT '6'
  UNION SELECT '7') x
LEFT JOIN (  
   SELECT
      CASE when (`ServedTimeStamp` BETWEEN Max(`ServedTimeStamp`) - INTERVAL 1 DAY AND Max(`ServedTimeStamp`)) then '1'
       when (`ServedTimeStamp` BETWEEN Max(`ServedTimeStamp`) - INTERVAL 2 DAY AND Max(`ServedTimeStamp`) - INTERVAL 1 DAY) then '2'
       when (`ServedTimeStamp` BETWEEN Max(`ServedTimeStamp`) - INTERVAL 3 DAY AND Max(`ServedTimeStamp`) - INTERVAL 2 DAY) then '3'
       when (`ServedTimeStamp` BETWEEN Max(`ServedTimeStamp`) - INTERVAL 4 DAY AND Max(`ServedTimeStamp`) - INTERVAL 3 DAY) then '4'
       when (`ServedTimeStamp` BETWEEN Max(`ServedTimeStamp`) - INTERVAL 5 DAY AND Max(`ServedTimeStamp`) - INTERVAL 4 DAY) then '5'
       when (`ServedTimeStamp` BETWEEN Max(`ServedTimeStamp`) - INTERVAL 6 DAY AND Max(`ServedTimeStamp`) - INTERVAL 5 DAY) then '6'
       when (`ServedTimeStamp` BETWEEN Max(`ServedTimeStamp`) - INTERVAL 7 DAY AND Max(`ServedTimeStamp`) - INTERVAL 6 DAY) then '7'
  END AS DateRange,
  COUNT(*) as TotalWithinRange
FROM `AdServing`
WHERE `UserID` = 123
GROUP BY 1 ) y ON x.DateRange = y.DateRange

但是 mySQL 提示:“无法在 'DateRange' 上分组”- 我并不完全理解。我是 SQL 的新手。以及大多数其他事情。

无论如何,如果有任何帮助,我将不胜感激。并为冗长的问题道歉。

最佳答案

一个通用版本,因为我今天有点忙不过来了:

SELECT MIN(dtField), MAX(dtField) INTO @first, @last 
FROM theTable 
WHERE [conditions]
;

SET @interval := DATEDIFF(@last, @first) / [number of datapoints you want];

SELECT DATEDIFF(dtField, @first) DIV @interval AS dateRange
, COUNT(1) AS TotalWithinRange
FROM theTable
WHERE [same conditions as the first query]
GROUP BY dateRange
;

编辑 1:糟糕,错过了区间上的除数。

编辑 2:请注意,这假设至少有 7 天。如果你想要更好的粒度,你可以使用额外的 functions将其缩小到秒精度。

关于mySQL,按日期分组数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32059828/

相关文章:

sql - 用于查找前两条记录和最后一条记录的特殊 SQL 条件查询?

java - 如何将日期删除为字符串格式?

php - Laravel 选择具有唯一列的行

mysql - 如何计算线路之间的平均时间差?

python - 根据日期列范围将列添加到数据框

java - 如何在java中存储、排序和分组项目(列表/设置/映射)?

sql-server - sql server查询将列中的行分为四组或四列

ruby-on-rails - Rails has_many 通过、分组和汇总数据

mysql更新更新表中的所有用户行

php - php 中的分页不起作用