Customers Holidays id | name customer_id | start | end ---+------ ------------+--------+------ 1 | Peter 1 | 5 | 10 2 | Simon 1 | 15 | 20 3 | Mary 2 | 5 | 20
什么是有效的SQL查询,在特定日期为所有客户提供没有假期? E.g。日期= 12
这是否可以通过简单的SQL连接进行管理,还是需要使用子查询?
答案 0 :(得分:6)
首先创建一个查找与您想要的相反的查询:在该特定日期有假期的客户:
SELECT DISTINCT name
FROM Customers
JOIN Holidays
ON id = customer_id
WHERE start <= 12 AND end >= 12
结果:
Simon
然后将此结果连接回customer表并选择连接失败的结果:
SELECT name
FROM Customers
LEFT JOIN (
SELECT DISTINCT id
FROM Customers
JOIN Holidays
ON id = customer_id
WHERE start <= 12 AND end >= 12
) AS T1
ON Customers.id = T1.id
WHERE T1.id IS NULL
结果:
Peter
Mary
请注意,JOIN不是此处的唯一选择。您还可以使用NOT EXISTS
,NOT IN
或EXCEPT
。由于您没有指定哪个数据库,我选择了JOIN,因为它是一种可移植且有效的方法,可以在所有主要关系数据库中执行此操作。
我使用的测试数据(取自问题):
CREATE TABLE Holidays (customer_id INT NOT NULL, start INT NOT NULL, end INT NOT NULL);
INSERT INTO Holidays (customer_id, start, end) VALUES
(1, 5, 10),
(1, 15, 20),
(2, 5, 20);
CREATE TABLE Customers (id INT NOT NULL, name NVARCHAR(100) NOT NULL);
INSERT INTO Customers (id, name) VALUES
(1, 'Peter'),
(2, 'Simon'),
(3, 'Mary');
答案 1 :(得分:1)
我认为你正在寻找这个:
declare @myStart int
declare @myEnd int
SET @myStart = 11
SET @myEnd = 14
SELECT c.name
FROM Customers c
INNER JOIN Holidays h
ON c.id=h.customer_id
WHERE
(@myStart BETWEEN h.start AND h.end) OR
(@myEnd BETWEEN h.start AND h.end) OR
(@myStart < h.start AND @myEnd > h.end)
答案 2 :(得分:1)
你可以这样做
-- Get customers only from Customers table
SELECT name FROM Customers
WHERE id NOT IN ( -- Get the intersection between the two tables
SELECT id FROM Customers JOIN
Holidays ON Customers.Id = Holidays.customer_id
WHERE Holidays.start=12 AND Holidays.end = 12)
答案 3 :(得分:0)
我不认为您想“删除”任何内容,只需选择与您的开始/结束值重叠的值,对吗?试试这个
SELECT
Name
FROM
Customers c
JOIN Holidays h on h.Customer_id = c.ID
WHERE
Start >= @Start
OR End <= @End
答案 4 :(得分:0)
select
c.name
from
Customers c
left outer join
Holidays h
on
h.customer_id=c.id
where
h.start <= 11
and
h.end >= 14
group by
c.id