这是我的问题的简化版本。我有一个包含名称的表和一个包含有限时隙列表的表(比如一周中的几天)链接器表链接这两个表。使用这三个表的简单内连接,我可以显示每个人的可用性:
| id | day |
|******|*****|
| 1 | MO |
| 1 | TU |
| 1 | WE |
| 1 | TH |
| 1 | FR |
| 1 | SU |
| 2 | MO |
| 2 | TU |
| 2 | WE |
| 2 | FR |
| 2 | SA |
| 2 | SU |
由于大多数用户大多数时间都可以使用,因此我想运行一个查询来显示他们不的时间:
| id | day |
|******|*****|
| 1 | SA |
| 2 | TH |
我知道如何使用外连接和WHERE找到集合的补集... IS NULL,但我看不出如何将这些互补值链接到个人。这可能是非常明显的事情,但我已经坚持了几个小时。请注意,我无法控制数据库设计。
编辑:我为我的问题不够清楚而道歉。我会再试一次。
表个人具有以下列:id(PK),first_name,last_name,DOB等。 表时隙具有以下列:id(PK),时间段 链接器表个人时间段具有以下列:id(PK),idindividual(FK),idtimeslot(FK)
以下查询返回个人可用时的概述。
SELECT
i.first_name, i.last_name, t.timeslot
FROM
individuals as i
inner join individualstimeslots as it on it.idindividual = i.id
inner join timeslots as t on t.id = it.idtimeslot
(结果类似于上面的第一个表,除了名字和姓氏而不是id)
如果我想知道id 1的个人何时不可用,我可以使用以下查询:
SELECT
i.first_name, i.last_name, t.timeslot, t2.timeslot as all
FROM
individuals as i
inner join individualstimeslots as it on it.idindividual = i.id and i.id = 1
inner join timeslots as t on t.id = it.idtimeslot
right outer join timeslots as t2 on t.id = t2.id
具有以下结果:
| JOHN | DOE | MO | MO |
| JOHN | DOE | TU | TU |
| JOHN | DOE | WE | WE |
| JOHN | DOE | TH | TH |
| JOHN | DOE | FR | FR |
| | | | SA |
| JOHN | DOE | MO | SU |
如果我只想显示John Doe不可用的时间段,我可以在查询中添加以下条件:
WHERE t.timeslot IS NULL
结果:
| | | | SA |
然而,此结果并未明确指代id = 1的个人。 我所追求的是一个查询,只有当所有(选定)个人
时才会这样做并显示:| JOHN | DOE | SA |
| JANE | DOE | TH |
希望我现在让自己更清楚了。
答案 0 :(得分:0)
不幸的是,我不认为你可以通过一个简单的查询来解决这个问题(我想证明这是错误的)。 但是您可以轻松地创建一个循环遍历所有(相关)个体的游标,并且每个人都执行外部联接查询。然后,您可以将结果插入临时表中,并从最后选择。 你已经标记了mysql和sql-server,所以我不知道你使用哪种语言。但这两种情况都有可能:)
答案 1 :(得分:0)
此查询似乎可以执行您想要的操作。你甚至可以在没有CTE的情况下重写它,但我认为它更清楚。
INSERT INTO dbo.days (namedays) VALUES
('Monday'),
('Tuesday'),
('Wednesday'),
('Thursday'),
('Friday'),
('Saturday'),
('Sunday')
INSERT INTO availability (ID,namedays) VALUES
(1,'Monday'),
(1,'Tuesday'),
(1,'Thursday'),
(2,'Monday'),
(2,'Saturday')
;WITH CTE AS (
SELECT DISTINCT a.ID AS ID ,d.namedays FROM availability a
CROSS JOIN dbo.days d)
SELECT CTE.ID, CTE.namedays FROM CTE
LEFT OUTER JOIN availability a
ON a.ID = CTE.ID AND a.namedays = CTE.namedays
WHERE a.ID IS NULL