之前已经提出过这个问题的不同变体,但对于我正在寻找的用例都没有。我想在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
)。因此,对于start
和end
日期值为2016-01-01
和2016-03-01
的记录,我想知道该记录仅在{{{}}发生的频率{1}}至2016-01-01
,包括在内。我最初尝试通过创建一个包含所有日期值的表来实现这一目标,这些日期值将来会持续多年:
2016-01-31
然后将datevalue
---------
2016-01-01
2016-01-02
...
加入input
和start_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中有更有效的方法吗?
答案 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(end, start) DIV 7
div
未涵盖的小数周的天数。