如何创建检查时间重叠的查询?

时间:2015-07-09 18:49:56

标签: sql database ms-access ms-access-2010

说我想编写一个查询,查找在任意时段可用的所有教授。我有一张教授的桌子,每个教授都没有时间。

教授表中有每个教授的条目,他们的名字和他们忙的时间段(所以有多个繁忙时段的教授会有多个条目)。

我的问题是,如果教授在特定时间段x已经忙碌并且在另一个时间段y忙碌,那么将返回教授可用于x,因为y不会干扰。

所以说我需要找到一个在下午12点可用的教授名单。琼斯教授在中午12点忙碌,下午2点也很忙。我提出的每个查询都会返回教授琼斯,因为它在下午2点看到该条目,并且知道这不会重叠。 (实际查询需要是通用的,因此它会遍历时间列表并返回一个包含每个时隙的大表,每个教授在该时隙可用,而不是SELECT time WHERE time = "12"

1 个答案:

答案 0 :(得分:1)

根据您的描述和评论,我假设您有以下表格结构:

professor
- name string
- start datetime
- end datetime

根据您的描述,不清楚查询的输入是单个时间点还是时间范围。然后你继续提到解决方案需要是通用的'以便它通过时间列表#39;这个清单是什么?你在哪里得到它?如需更全面的答案,我需要您给我一个更好的描述。

但是现在,我将假设查询的输入是一个名为$ checktime的日期时间值,并且您正在尝试查找在该确切时刻可用的教授列表。时间。将其改为一段时间应该相当简单。

根据您当前查询的问题描述,听起来像当前查询是这样的:

SELECT DISTINCT name
FROM professor 
WHERE $checktime < start 
    OR $checktime > end

如果您有两个条目(琼斯,下午12点,下午1点)和(琼斯,下午2点,下午3点),并使用$ checktime = 12pm运行该查询,where子句将过滤掉第一个条目,但第二个条目将保持不变,将Jones留在结果表中。这似乎与您提供的描述相符。

这里的诀窍是找到当时忙碌的所有教授的名单,然后使用该名单找到当时不忙的教授。

例如,从以下查询开始,这与您当前的查询基本相反。

SELECT DISTINCT name
FROM professor 
WHERE $checktime >= start
    AND $checktime <= end

这将为您提供当时忙碌的所有教授的名单。然后,您可以获得所有教授的列表,并使用MINUS删除上一个查询中包含的条目:

(
-- The list of all professors
SELECT DISTINCT name
FROM professor
)
MINUS
(
-- The list of all professors who are busy at the given time slot.
SELECT DISTINCT name
FROM professor 
WHERE $checktime >= start
    AND $checktime <= end 
)

其余的教授都是在给定时间内不忙的教授。

我不熟悉MS Access,但如果它恰好是不支持MINUS的数据库引擎之一,那么你可以改为执行以下操作,这在逻辑上是等价的(假设表教授有对于名称的约束不为null),但可读性要差得多:

SELECT DISTINCT all_profs.name
FROM professor as all_profs
LEFT JOIN 
    (SELECT DISTINCT name
    FROM professor 
    WHERE $checktime >= start
        AND $checktime <= end
    ) as busy_profs
ON all_profs.name = busy_profs.name
WHERE busy_profs.name IS NULL

作为旁注,您应该考虑更改表结构,以便繁忙时间位于与教授分开的表中,例如名为busy_times的新表,其中包含3列:教授(教授表的外键),启动,并结束。这是因为,据推测,你有更多关于教授的信息,而不仅仅是他们的名字,大多数教授都会有很多忙碌的时间。这会导致大量重复信息,这有两个原因。首先,它占用的空间比它应该多得多。其次,维护起来非常麻烦。如果教授结婚并改名,会发生什么?你必须改变每一个条目,如果你错过了它,它可能会导致问题。