I am using mySQL to build an application where a customer can pick available dates.
I want two queries, one that specifies what slots each customer picked and one the specifies which date has not yet been picked.
The setup
I have a list of time slots in the form of dates
TABLE: timeslots
slot_id | date
1 | 2020-10-01
2 | 2020-10-02
3 | 2020-10-03
I also have a customer table
TABLE: customers
customer_id | name
1 | Anders
2 | Joe
3 | Karen
Each customer can pick whatever date they like which is specified in the customer_timeslot table which has two Foreign Keys.
TABLE: customer_timeslot
customer_id | slot_id
1 | 1
1 | 2
2 | 1
3 | 1
First query all good
The first query is easy enough and gives me the dates Anders has picked.
The query for the dates Anders (cust. 1) picked
SELECT timeslots.date AS Date, customer.name AS Customer FROM timeslots
JOIN customer_timeslot
USING (slot_id)
JOIN customers
USING (customer_id)
WHERE customers.customer_id = 1
Result query 1
Date | Customer
2020-10-01 | Anders
2020-10-02 | Anders
The result I want for the second query
I want the date Anders has not picked yet which would look like this
Date | Customer
2020-10-03 | Anders
What I've tried
I've tried to use LEFT JOIN instead of JOIN..
SELECT timeslots.date AS Date, customer.name AS Customer FROM timeslots
LEFT JOIN customer_timeslot
USING (slot_id)
JOIN customers
USING (customer_id)
WHERE customers.customer_id = 1
..Which i expected would give me this result but instead gives me the exact same as the INNER JOIN (No NULL to work with)
Date | Customer
2020-10-01 | Anders
2020-10-02 | Anders
2020-10-03 | NULL
How can i get the desired query? Shouldn't be so complicated I guess but I'm finding myself completely stuck and looking for some help.
You could use not exists
:
select t.*
from timeslots t
where not exists (
select 1
from customer_timeslot ct
where ct.customer_id = 1 and ct.slot_id = t.slot_id
)
This returns the timeslots that customer_id
1
did not pick. You can get the information for all customers at once with a cross join
, then not exists
:
select t.date, c.name
from timeslots t
cross join customers c
where not exists (
select 1
from customer_timeslot ct
where ct.customer_id = c.customer_id and ct.slot_id = t.slot_id
)