【问题标题】:SQL/Mysql Query available dates in databaseSQL/Mysql 查询数据库中的可用日期
【发布时间】:2017-01-25 13:04:32
【问题描述】:

我需要一些帮助来查询我的日历/日期表

场景: 我有一个带有日期的“日历”表,用户将设置他的可用日期,通常是一天一天。所以我的表是这样的:

+------+------------+---------------------+---------------------+ 
| ID   | user_id    | start_date          | end_date            | 
+------+------------+---------------------+---------------------+ 
|    1 |          1 | 2016-09-01 08:00:00 | 2016-09-01 16:00:00 | 
|    2 |          1 | 2016-09-03 08:00:00 | 2016-09-03 16:00:00 | 
|    3 |          1 | 2016-09-04 08:00:00 | 2016-09-04 16:00:00 | 
|    3 |          1 | 2016-09-05 08:00:00 | 2016-09-05 16:00:00 | 
+------+------------+---------------------+---------------------+ 

这意味着用户 1 在 1 日、3 日、4 日和 5 日可用。

假设我想查询表并查找用户是否从日期 2016-09-01 08:00:00 到 2016-09-05 16:00:00 可用,此查询必须返回零行,因为用户9 月 2 日不可用。但是如果从日期 2016-09-03 08:00:00 到 2016-09-05 16:00:00 查询,那么它将返回这 3 行。

希望有人能帮我解决这个问题

【问题讨论】:

  • 开始日期和结束日期可以不同吗?
  • 是的。否则我只会有日期列。但它们不能相互重叠。
  • 显示用户可用的所有行没有任何意义。

标签: mysql sql date web calendar


【解决方案1】:

这可能是一种方式(对于单个用户)。

注意@endDate@startDate 是提供的要搜索的日期字段。

SELECT 
*
FROM your_table 
WHERE EXISTS (
    SELECT 
    user_id
    FROM your_table 
    WHERE start_date >= @startDate 
    AND start_date <= @endDate
    AND user_id = 1
    GROUP BY user_id 
    HAVING SUM((DATEDIFF(end_date,start_date)+1)) = DATEDIFF(@endDate,@startDate)+1
)
AND start_date >= @startDate 
AND start_date <= @endDate
AND user_id = 1

注意:

如果提供的日期范围在start_dateend_date(不包括)限定的任何范围内,则它将不起作用。

因为SUM((DATEDIFF(end_date,start_date)+1)) = DATEDIFF(@endDate,@startDate)+1 在这种情况下不会相等。 条件

在这种情况下,您需要保持在所需的边界内。这里的边界由end_date@endDate 的较小值和start_date@startDate 的较大值划分。

假设,你有以下记录(只有一条)

start_date = 2016-09-01end_date=2016-09-05

还有@startDate=2016-09-02@endDate=2016-09-04

现在检查上述条件对于这组数据是否会失败。

在这种情况下,您需要采用以下查询:

SELECT 
*
FROM your_table 
WHERE EXISTS (
    SELECT 
    user_id
    FROM your_table 
    WHERE end_date >= @startDate 
    AND start_date <= @endDate
    AND user_id = 1
    GROUP BY user_id 
    HAVING SUM((DATEDIFF(LEAST(end_date,@endDate),GREATEST(start_date,@startDate))+1)) = DATEDIFF(@endDate,@startDate)+1
)
AND end_date >= @startDate 
AND start_date <= @endDate
AND user_id = 1

【讨论】:

  • 这很有效,并且在连接中也很容易理解和使用。非常感谢。
  • 还有一个问题,我该如何比较这个查询中的时间?
【解决方案2】:

假设表格中的期间不重叠,您可以计算天数。期间的天数是:

select sum(datediff(least($period_end, end_date),
                    greatest($period_start, start_date)
                   ) + 1
          )
from t
where $period_start <= end_date and
      $period_end >= start_date;

然后你可以通过比较天数来获得一个标志:

select (case when sum(datediff(least($period_end, end_date),
                               greatest($period_start, start_date)
                              ) + 1
                     ) =
                  datediff($period_end, $period_start) + 1
             then 1 else 0
        end) as IsAvailableForAllDays
from t
where $period_start <= end_date and
      $period_end >= start_date;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-01
    • 2013-03-11
    • 2015-01-18
    • 2014-03-21
    • 1970-01-01
    相关资源
    最近更新 更多