mysql - 如何在MySQL中高效查找两个日期之间的特定天数?

标签 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

示例用例

我这样做是因为我试图找到输入数据中不可用的时间范围内的行频率(称为输入)。因此,对于 startend 日期值为 2016-01-012016-03-01 的记录>,我想知道该记录仅在 2016-01-012016-01-31(含)之间出现的频率。我最初尝试通过制作一个包含 future 许多年的所有日期值的表格来实现此目的,例如:

datevalue
---------
2016-01-01
2016-01-02
...

然后在 start_dateend_dateinput 连接到该表,然后在计算每天的数量时进行汇总,如下所示:

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

这在较小的数据集上完美运行,但 input 有超过 3000 万条记录,当我尝试运行该过程时,它运行了 36 小时,然后我将其终止。

在 MySQL 中是否有更有效的方法来执行此操作?

最佳答案

评论太长了,但是结合我最初建议的工作日的预先计算,这会产生多少(使用单个 SUM 和完整的 CASE)适合你吗?

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 未涵盖的小数周要添加的天数。

关于mysql - 如何在MySQL中高效查找两个日期之间的特定天数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38922759/

相关文章:

sql - 加入时间太长

mysql - 我如何在 ubuntu 服务器的 mysql 中导入我的数据库转储文件

android - DatePicker 的 setMinDate(...) 在第二次调用时不起作用

javascript - JS定时器在IE8中显示NaN

javascript - 使用 Jquery 更改日期格式

MySQL 加入无重复

javascript - 如何使实时源列表仅在事件选项卡上更新或在选项卡再次变为事件状态时更新?

mysql - 将离线数据库与 Google Appengine 数据库 Cron 作业同步

mysql - Bigquery 表基于日期的前导列值

android - Sqlite,连接表: ambiguous column error