MySQL计算表格上两个日期之间的星期几

时间:2017-10-06 21:01:00

标签: mysql count dayofweek

我有一张包含以下栏目的预订表:

id,start_date,end_date

我想知道哪些日子对我的数据集的预订最多。

我可以在开始日期使用dayofweek()并按此分组,并使用count(*)。但我也希望包括预订开始和结束之间的日子。

示例输出

dayofweek     count(*)
1             1
2             1
3             1
4             2
5             3
6             3
7             1

用于以下集合

id       start_date          end_date
1        2017-10-01          2017-10-07
2        2017-10-04          2017-10-07
3        2017-10-06          2017-10-08

2 个答案:

答案 0 :(得分:0)

您可以使用递归表来完成此操作:

WITH cte AS
(
    SELECT DATE_ADD(start_date INTERVAL 1 DAY) AS date, end_date, DAYOFWEEK(start_date) AS dw from bookings
    UNION ALL 
    SELECT DATE_ADD(start_date INTERVAL 1 DAY), end_date, DAYOFWEEK(date)
    FROM cte WHERE date <= end_date
)
SELECT COUNT(*), dw FROM cte GROUP BY dw

答案 1 :(得分:0)

我假设您希望知道在开始和结束之间的持续时间内每个日期填充的房间数量。这里的“技巧”是开始/结束之间的长时间段将重复一天或一周和/或一周结束日可能小于一周的开始日期。所以,我有:

  1. 生成了100,000个日期(每行1个)的列表
  2. 在表格的开头/结尾之间加入了这些日期
  3. 将每个已加入的行转换为要计算的星期数
  4. 左连接到1到7的列表,并计算步骤3的行
  5. 注意:如果end_date是“结账日期”,则可能需要从每条记录中扣除1天以进行补偿(以下不做)。

    此方法可在SQL Fiddle

    处查看

    MySQL 5.6架构设置

    CREATE TABLE Table1
        (`id` int, `start_date` datetime, `end_date` datetime)
    ;
    
    INSERT INTO Table1
        (`id`, `start_date`, `end_date`)
    VALUES
        (1, '2017-09-21 00:00:00', '2017-10-07 00:00:00'), ## added this row
        (1, '2017-10-01 00:00:00', '2017-10-07 00:00:00'),
        (2, '2017-10-04 00:00:00', '2017-10-07 00:00:00'),
        (3, '2017-10-06 00:00:00', '2017-10-08 00:00:00')
    ;
    

    <强>查询

    set @commence := str_to_date('2000-01-01','%Y-%m-%d')
    
    select
        w.dy
      , count(t.wdy)
    from (
          select 1 dy union all select 2 dy union all select 3 dy union all
          select 4 dy union all select 5 dy union all select 6 dy union all select 7 dy
          ) w
    left join (
          select DAYOFWEEK(cal.dy) wdy
          from (
                  select adddate( @commence ,t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) dy 
                  from  (     select 0 i union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t0 
                  cross join (select 0 i union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t1 
                  cross join (select 0 i union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t2 
                  cross join (select 0 i union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t3 
                  cross join (select 0 i union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t4
              ) cal
          INNER JOIN Table1 t on cal.dy between t.start_date and t.end_date
          ) t on w.dy = t.wdy
    group by
        w.dy
    

    <强> Results

    | dy | count(t.wdy) |
    |----|--------------|
    |  1 |            4 |
    |  2 |            3 |
    |  3 |            3 |
    |  4 |            4 |
    |  5 |            5 |
    |  6 |            6 |
    |  7 |            6 |
    

    另请参阅:How to get list of dates between two dates in mysql select query其中,接受的答案是从指定日期开始生成100,000个日期的交叉联接集的基础。然而,我修改了语法(显式交叉连接语法),参数作为起点,并使用union all来提高效率。