帮助形成 mysql 查询以查找给定日期范围的免费(可用)场所/资源

Posted

技术标签:

【中文标题】帮助形成 mysql 查询以查找给定日期范围的免费(可用)场所/资源【英文标题】:help in forming mysql query to find free(available) venues/resources for a give date range 【发布时间】:2011-01-04 05:42:19 【问题描述】:

我有这样的表格和数据:

场地表包含:id +----+----------+ |编号 |姓名 | +----+----------+ | 1 |场地1 | | 2 |场地2 | --------------- event_dates : id、event_id、event_from_datetime、event_to_datetime、venue_id +----+----------+----------+---------- ----------+----------+ |编号 | event_id | event_from_datetime | event_to_datetime |场地_id | +----+----------+----------+---------- ----------+----------+ | 1 | 1 | 2009-12-05 00:00:00 | 2009-12-07 00:00:00 | 1 | | 2 | 1 | 2009-12-09 00:00:00 | 2009-12-12 00:00:00 | 1 | | 3 | 1 | 2009-12-15 00:00:00 | 2009-12-20 00:00:00 | 2 | +----+----------+----------+---------- ----------+----------+

这是我的要求:我想要在 2009-12-06 00:00:00 免费的场地 即

我应该得到

|venue_id|

|2 |

目前我有以下查询,

选择 ven.id , evtdt.event_from_datetime, evtdt.event_to_datetime 从场地文 离开加入 event_dates evtdt 开 (ven.id=evtdt.venue_id) 其中 evtdt.venue_id 为空 与否('2009-12-06 00:00:00' 在 evtdt.event_from_datetime 之间 和 evtdt.event_to_datetime); +----+----------+----------+ |编号 | event_from_datetime | event_to_datetime | +----+----------+----------+ | 1 | 2009-12-09 00:00:00 | 2009-12-12 00:00:00 | | 2 | 2009-12-15 00:00:00 | 2009-12-20 00:00:00 | | 3 |空 |空 | | 5 |空 |空 | +----+----------+----------+

如果您注意到结果,它不包括日期在 2009-12-06 00:00:00 之间的场地 id 1,但显示其他预订。 请帮我更正这个查询。

提前致谢。

【问题讨论】:

@Anitha:您能否编辑您的问题并添加您期望的结果以及原因? 嗨,彼得,感谢您的回复。我已经编辑了这个问题。如果现在有意义,请告诉我。再次感谢。 另外,您发布的结果明显不是执行您提供的查询的结果,如下面我的帖子中所述... 【参考方案1】:
or not ('2009-12-06 00:00:00' between evtdt.event_from_datetime 
                              and evtdt.event_to_datetime);

2009 年 12 月 6 日 在 2009 年 9 月 5 日到 2009 年 12 月 7 日之间...这就是为什么会场 ID 1 被排除在外...您要提取的内容是什么究竟是从数据中得到的?

您构建的连接查询说,获取场地表,并为其中具有匹配场地_id 的每一行制作场地表行的副本并附加匹配的行。因此,如果您刚刚这样做:

select * 
  from venues ven 
  left join event_dates evtdt 
  on (ven.id=evtdt.venue_id);

它会产生:

+----+---------+------+----------+---------------------+---------------------+----------+
| id | name    | id   | event_id | event_from_datetime | event_to_datetime   | venue_id |
+----+---------+------+----------+---------------------+---------------------+----------+
|  1 | venue 1 |    1 |        1 | 2009-12-05 00:00:00 | 2009-12-07 00:00:00 |        1 |
|  1 | venue 1 |    2 |        1 | 2009-12-09 00:00:00 | 2009-12-12 00:00:00 |        1 |
|  2 | venue 2 |    3 |        1 | 2009-12-15 00:00:00 | 2009-12-20 00:00:00 |        2 |
+----+---------+------+----------+---------------------+---------------------+----------+

如果您随后添加了条件,表明感兴趣的日期不在事件的开始日期和结束日期之间,则查询如下所示:

select * 
  from venues ven 
  left join event_dates evtdt 
  on (ven.id=evtdt.venue_id) 
  where not ('2009-12-06' between evtdt.event_from_datetime and evtdt.event_to_datetime)

这会产生以下结果:

+----+---------+------+----------+---------------------+---------------------+----------+
| id | name    | id   | event_id | event_from_datetime | event_to_datetime   | venue_id |
+----+---------+------+----------+---------------------+---------------------+----------+
|  1 | venue 1 |    2 |        1 | 2009-12-09 00:00:00 | 2009-12-12 00:00:00 |        1 |
|  2 | venue 2 |    3 |        1 | 2009-12-15 00:00:00 | 2009-12-20 00:00:00 |        2 |
+----+---------+------+----------+---------------------+---------------------+----------+

这些是我在 mysql 中对您的数据进行的实际实验结果。

如果您想在建议的日期获得免费的场地 ID,那么您可以编写如下内容:

  select ven.id, SUM('2009-12-06' between evtdt.event_from_datetime and evtdt.event_to_datetime) as num_intersects 
    from venues ven left join event_dates evtdt on (ven.id=evtdt.venue_id) 
    group by ven.id
    having num_intersects = 0;

产生:

+----+----------------+
| id | num_intersects |
+----+----------------+
|  2 |              0 |
+----+----------------+

如果您有一个在 event_date 表中没有活动的场地,这也会得出正确的答案(无需修改)。

【讨论】:

【参考方案2】:
SELECT  *
FROM    venue v
WHERE   NOT EXISTS
        (
        SELECT  NULL
        FROM    event_dates ed
        WHERE   ed.venue_id = v.id
                AND '2009-12-06 00:00:00' BETWEEN ed.event_from_datetime AND ed.event_to_datetime
        )

【讨论】:

并非相反,但我相信您可以避免使用连接和过滤操作就足够的子查询。我认为通过适当地索引表并执行最初建议的连接,您可以获得显着的性能提升。 @vicatcu: MySQL 足够聪明,可以优化子查询。请在我的博客中阅读这篇文章:explainextended.com/2009/09/18/…【参考方案3】:

猜测一下,如果你从

中删除 not
or not ('2009-12-06 00:00:00' between evtdt.event_from_datetime 
                                  and evtdt.event_to_datetime)

这将从事件日期返回第 1 行,但不返回其他事件日期行。

我说“猜测”是因为您的 where 子句有点难以理解。也许你的意思是

select ven.id , evtdt.event_from_datetime, evtdt.event_to_datetime 
from venues ven 
left join event_dates evtdt 
on (ven.id=evtdt.venue_id) 
where '2009-12-06 00:00:00' between evtdt.event_from_datetime 
                                  and evtdt.event_to_datetime;

【讨论】:

嗨,史蒂夫,为了更清楚,我再次编辑了我的问题。此外,左连接是获取可能根本没有任何预订的场所(意味着 event_dates 表中没有行,但场所表中有行条目)。感谢您的回复。

以上是关于帮助形成 mysql 查询以查找给定日期范围的免费(可用)场所/资源的主要内容,如果未能解决你的问题,请参考以下文章

使用未在 Mysql 中排序的多个日期范围查询给定月份的日期范围间隙

Mysql - 使用多个连接表查找丢失的日期

MySql 查询以查找给定日期“从”和“到”可用的房间

Mysql查询 - 返回两个日期范围相交的日期

MySQL:查找日期范围之间的缺失日期

我如何查询给定日期范围的mysql并加入两个表?