mySQL,按日期分组数据

时间:2015-08-17 21:15:39

标签: mysql date grouping

你好:这个问题似乎已经有很多变化了,但是我无法根据自己的需要调整其中任何一个(不管怎么样都不行。)

我有一张这样的表:

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。还有其他大部分事情。

无论如何,我会非常感激任何帮助。并为这个冗长的问题道歉。

1 个答案:

答案 0 :(得分:1)

一个通用版本,因为我今天有点淹没了:

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天。如果你想要更好的granualarity,你可以使用额外的functions将其缩小到秒精度。