帮助形成 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】:
猜测一下,如果你从
中删除 notor 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 查询以查找给定日期范围的免费(可用)场所/资源的主要内容,如果未能解决你的问题,请参考以下文章