I'm trying to create a query which gets all columns and a case column which denotes availablity, however I need to include a one to many relationship in the mix and it's messing with my head.
My query without the relationship:
SELECT storage_rooms.*,
CASE
WHEN release_date <= CURDATE() THEN 1
WHEN release_date <= ADDDATE(CURDATE(), INTERVAL 30 DAY) THEN release_date
ELSE 0
END AS available
FROM storage_rooms
Which is fine and returns something like this:
Now I need to check if it is already booked. To give you an idea of what I'm thinking (doesn't work):
SELECT storage_rooms.*,
(SELECT
CASE
WHEN release_date <= CURDATE() OR orders.status_id IN (3, 4) THEN 1
WHEN release_date <= ADDDATE(CURDATE(), INTERVAL 30 DAY) THEN release_date
ELSE 0
END AS available
FROM storage_rooms
LEFT OUTER JOIN orders
ON storage_rooms.id = orders.storage_room_id)
FROM storage_rooms
I gather I might need another subquery with a groupBy? I don't find joins super intuitive and I'm a bit lost so any assistance would be welcome.
I'm not totally sure it will work but you can try this:
SELECT storage_rooms.*,
CASE
WHEN release_date <= CURDATE() OR availibility.order_status_id IN (3, 4) THEN 1
WHEN release_date <= ADDDATE(CURDATE(), INTERVAL 30 DAY) THEN release_date
ELSE 0
END AS available
FROM storage_rooms
LEFT JOIN
( SELECT id AS order_id, status_id AS order_status_id, storage_room_id AS order_storage_room_id
FROM orders WHERE status_id IN (3, 4)
GROUP BY storage_room_id
) availibility
ON (storage_rooms.id = availibility.order_storage_room_id)
The thing here is that the LEFT JOIN
is adding to the results the columns needed to check your availability. But the trick is you need a subquery so that the table joined contains only one entry for each room or else the results are duplicated. The subquery must be limited to the positive matches you want to take in consideration with a WHERE
, because the GROUP BY
will only keep the first row found and you don't want this information lost in the grouping.
FROM OP'S COMMENTS THE FINAL QUERY IS:
SELECT storage_rooms.*,
CASE
WHEN release_date <= CURDATE() OR aggregate.order_status_id IS NULL THEN 1
WHEN release_date <= ADDDATE(CURDATE(), INTERVAL 30 DAY) THEN release_date
ELSE 0
END AS available
FROM storage_rooms
LEFT JOIN
(SELECT storage_room_id, order_status_id
FROM orders WHERE order_status_id IN (1, 2)
GROUP BY storage_room_id, order_status_id
) aggregate
ON storage_rooms.id = aggregate.storage_room_id
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.