First create a query that finds the opposite of what you want: the customers who do have a holiday on that specific date:
SELECT DISTINCT name
FROM Customers
JOIN Holidays
ON id = customer_id
WHERE start <= 12 AND end >= 12
Result:
Simon
Then join this result back to the customer table and select the results where the join fails:
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
Result:
Peter
Mary
Note that a JOIN isn't the only alternative here. You could also use NOT EXISTS
, NOT IN
or EXCEPT
. Since you didn't specify which database, I chose JOIN because it is a portable and efficient way to do it in all the major relational databases.
The test data I used (taken from the question):
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');