如何有效地查找MySQL中两个日期之间的特定日期数?

时间:2016-08-12 16:36:43

标签: mysql date join group-by

之前已经提出过这个问题的不同变体,但对于我正在寻找的用例都没有。我想在MySQL表的每一行的两个日期之间找到特定的工作日数,然后用该操作的结果更新每一行的列。这是ETL过程的一部分,如果可能的话,我希望将其保存在存储过程中。

数据

日期属于DATE类型,我想查找特定的号码,因为如果在一周的某一天发生记录,我有7个day列有标记。像这样(1是星期一):

day_1 | day_2 | day_3 | day_4 | day_5 | day_6 | day_7
----- | ----- | ----- | ----- | ----- | ----- | -----
0     | 1     | 0     | 1     | 1     | 0     | 1

示例用例

我这样做是因为我试图在输入数据中找不到时间范围的行频率(称之为input)。因此,对于startend日期值为2016-01-012016-03-01的记录,我想知道该记录仅在{{{}}发生的频率{1}}至2016-01-01,包括在内。我最初尝试通过创建一个包含所有日期值的表来实现这一目标,这些日期值将来会持续多年:

2016-01-31

然后将datevalue --------- 2016-01-01 2016-01-02 ... 加入inputstart_date上的该表,然后汇总,同时计算每天的数量,如下所示:

end_date

这适用于较小的数据集,但SUM(CASE WHEN WEEKDAY(B.datevalue) + 1 = 1 THEN 1 ELSE 0 END) * day_1 + SUM(CASE WHEN WEEKDAY(B.datevalue) + 1 = 2 THEN 1 ELSE 0 END) * day_2 + SUM(CASE WHEN WEEKDAY(B.datevalue) + 1 = 3 THEN 1 ELSE 0 END) * day_3 + SUM(CASE WHEN WEEKDAY(B.datevalue) + 1 = 4 THEN 1 ELSE 0 END) * day_4 + SUM(CASE WHEN WEEKDAY(B.datevalue) + 1 = 5 THEN 1 ELSE 0 END) * day_5 + SUM(CASE WHEN WEEKDAY(B.datevalue) + 1 = 6 THEN 1 ELSE 0 END) * day_6 + SUM(CASE WHEN WEEKDAY(B.datevalue) + 1 = 7 THEN 1 ELSE 0 END) * day_7 AS adj_total_frequency 具有> 3000万条记录,当我尝试运行该程序时,它在我杀死它之前运行了36个小时。

在MySQL中有更有效的方法吗?

1 个答案:

答案 0 :(得分:1)

评论太长了,但结合我最初建议的工作日的预先计算,这个(使用一个SUM一个完整的CASE)可以为您做多少工作?< / p>

SUM(CASE WHEN B.weekdayval = 1 AND day_1 THEN 1
        WHEN B.weekdayval = 2 AND day_2 THEN 1
        WHEN B.weekdayval = 3 AND day_3 THEN 1
        WHEN B.weekdayval = 4 AND day_4 THEN 1
        WHEN B.weekdayval = 5 AND day_5 THEN 1
        WHEN B.weekdayval = 6 AND day_6 THEN 1
        WHEN B.weekdayval = 7 AND day_7 THEN 1 
        ELSE 0 END) AS adj_total_frequency
实际上这可能会更好;它可能理论上意味着B.weekdayval每行只进行一次比较(我说理论上因为MySQL不保证不相关THEN条款不会被评估,只是没有从“CASE”“返回”。

SUM(CASE WHEN day_1 THEN B.weekdayval = 1
        WHEN day_2 THEN B.weekdayval = 2
        WHEN day_3 THEN B.weekdayval = 3
        WHEN day_4 THEN B.weekdayval = 4
        WHEN day_5 THEN B.weekdayval = 5
        WHEN day_6 THEN B.weekdayval = 6
        WHEN day_7 THEN B.weekdayval = 7 
        ELSE 0 END) AS adj_total_frequency

编辑:就使用datesub方法而言,我没有时间编写完整的解决方案,而是启动你(或其他潜在的回答者)......

  • 我的意思是DATEDIFF
  • 您可以使用DATEDIFF(end, start) DIV 7
  • 获取开始和结束之间的整周数
  • 乘以适用于获得近似值的一周中的天数
  • 然后(最难的部分),计算div未涵盖的小数周的天数。