我有一个表,有两列,日期和分数。它最多有30个条目,过去30天中的每一天都有一个。
date score
-----------------
1.8.2010 19
2.8.2010 21
4.8.2010 14
7.8.2010 10
10.8.2010 14
我的问题是缺少一些日期-我想看看:
date score
-----------------
1.8.2010 19
2.8.2010 21
3.8.2010 0
4.8.2010 14
5.8.2010 0
6.8.2010 0
7.8.2010 10
...
我需要从单个查询中得到:19,21,9,14,0,0,10,0,0,14...这意味着缺少的日期将用0填充。
我知道如何得到所有的值,并在服务器端语言迭代通过日期和失踪的空白。但这是否可能在mysql中做到,这样我就可以按日期对结果进行排序,并得到缺失的部分。
编辑:在这个表中有另一个名为UserID的列,所以我有30.000个用户,其中一些在这个表中得分。我每天删除的日期,如果日期< 30天前,因为我需要为每个用户的最后30天得分。原因是我在过去30天的用户活动的图形和绘制一个图表,我需要用逗号分隔的30个值。因此,我可以在查询中说“get me the USERID=10203 activity”,然后该查询将为我获得30个分数,过去30天中的每一天都有一个。我希望我现在更清楚了。
7条答案
按热度按时间dw1jzc5e1#
MySQL没有递归功能,所以你只能使用NUMBERS表技巧-
1.创建一个只包含递增数字的表-使用auto_increment很容易做到:
1.使用以下命令填充表:
...您需要多少值都行。
1.使用DATE_ADD构造日期列表,根据www.example.com值增加天数NUMBERS.id。将“2010-06-06”和“2010-06-14”替换为相应的开始和结束日期(但使用相同的格式,YYYY-MM-DD)-
1.基于时间部分左联接到数据表:
如果要保持日期格式,请使用DATE_FORMAT函数:
hjqgdpho2#
我不是一个球迷的其他答案,需要创建表等。此查询无需帮助表即可高效地执行此操作。
让我们来剖析一下。
if将检测没有得分的天数并将其设置为0。B.天数是您选择从当前日期获取的已配置天数,最多1000天。
这个子查询是我在stackoverflow上看到的。它有效地生成从当前日期开始的过去1000天的列表。结尾的WHERE子句中的间隔(当前为30)决定返回哪些天;最大值为1000。这个查询可以很容易地修改为返回100年的日期,但1000年应该对大多数事情都有好处。
这是将包含分数的表带入其中的部分。与从日期生成器查询中选择的日期范围进行比较,以便能够在需要的地方填写0(最初将分数设置为
NULL
,因为它是LEFT JOIN
;这在select语句中是固定的)。我也是按日期订购的,只是因为。这是偏好,您也可以按分数排序。在
ORDER BY
之前,您可以轻松地与您在编辑时提到的用户信息表连接,以添加最后一个要求。我希望这个版本的查询可以帮助到一些人。感谢阅读。
jobtbby33#
自从这个问题被提出以来,时间已经过去了。MySQL 8.0于2018年发布,增加了对递归公共表表达式的支持,为这个问题提供了一个优雅的,最先进的解决方案。
下面的查询可用于生成日期列表,例如2010年8月的前15天:
然后你可以用你的表
left join
这个结果集来生成预期的输出:Demo on DB Fiddle:
请注意,非常容易使递归CTE适应于其他间隔或时段。举个例子,假设我们想要在2010年8月1日从4 AM到8 AM每15分钟一行;我们可以做到:
mepcadol4#
您可以使用日历表来完成此操作。这是一个你创建一次并填充一个日期范围的表(例如2000-2050年每天一个数据集;这取决于您的数据)。然后,您可以对日历表进行表的外部连接。如果表中缺少日期,则返回0作为分数。
yqlxgs2m5#
Michael Conard的回答很棒,但我需要15分钟的间隔,时间必须始终从每15分钟的顶部开始:
这会将当前时间设置为上一轮的第15分钟:
这将以15分钟的步长删除时间:
如果有更简单的方法,请告诉我。
sczxawaw6#
您可以通过插入从开始日期到今天的用户直接
2skhul337#
如果你是加入这个日历表,那么你可能会使用这个。这可以帮助您生成表中最小和最大日期之间的所有缺失日期沿着表中的其他列。