I try to create a query which shows available hotels between checkin and checkout dates. Also when I make a reservation for specific rooms, I set their booking column as 1. That means, when the checkout date comes in real life, a trigger function will set that booked column as 0.
If all rooms of a hotel are booked(booked=1) and checkin-checkout dates of those rooms are specific date(checkin-checkout inputs), then don't put that hotel in the list. My query doesn't show the result that I want.
Query: Inputs: Country(state), checkin and checkout.
SELECT DISTINCT a.* FROM accommodation a INNER JOIN cb_states s ON a.state = s.id
INNER JOIN accommodation_rooms ar ON a.id = ar.accommodation
WHERE state = 1 AND a.id NOT IN
(
SELECT 1 FROM booking b
WHERE
(
(b.arrival_date BETWEEN '2017-11-16' AND '2018-03-16')
OR
(b.departure_date BETWEEN '2017-11-16' AND '2018-03-16')
)
)
When I run the query, it always shows all hotels no matter dates. If I write ... WHERE ar.booked = 0 AND state = 1 AND a.id NOT IN..., then it doesn't show accommodation id 13, but it doesn't show either when I change dates.
accommodation table:
accommodation_rooms table:
booking table:
booked_rooms table:(has foreign key with booking table)
You have multiple issues with your query:
The NOT IN list has SELECT 1. That doesn't give a great variety to the NOT IN list.
Your logic for overlaps is wrong.
I think you need to connect accommodation rooms to booked accommodation rooms.
So:
SELECT DISTINCT a.*
FROM accommodation a INNER JOIN
cb_states s
ON a.state = s.id INNER JOIN
accommodation_rooms ar
ON a.id = ar.accommodation
WHERE s.state = 1 AND
a.id NOT IN (SELECT br.accommodation_room
FROM booking b JOIN
booked_room br
ON b.?? = br.??
WHERE b.arrival_date <= '2018-03-16' AND
b.departure_date >= '2017-11-16'
);
Related
I have two tables - one shows user purchases, and one shows a product id with it's corresponding product type.
My client wants to make duplicate users inactive based on last name and email address, but wants to run the query by product type (based on what type of product they purchased), and only wants to include user_ids who haven't purchased paint (product ids 5 and 6). So the query will be run multiple times - once for all people who have purchased lawnmowers, and then for all people who have purchased leafblowers etc (and there will be some overlap between these two). No user_id that has purchased paint should be made inactive.
In terms of who should stay active among the duplicates, the one to stay active will be the one with the highest product id purchased (as products are released annually). If they have multiple records with the same product id, the record to stay active will be the one with most recent d_modified and t_modified.
I also want to shift the current value of 'inactive' to the 'previously_inactive' column, so that this can be easily reversed if need be.
Here is some sample table data
If the query was run by leafblower purchases, rows 5, 6, and 7 would be made inactive. This is the expected output:
If the query was run by lawnmower purchases, rows 1 and 2 would be made inactive. This would be the expected output:
If row 4 was not the most recent, it would still not be made inactive, as user_id 888 had bought paint (and we want to exclude these user_ids from being made inactive).
This is an un-optimised version of the query for 'leafblower' purchases (it is working, but will probably be too slow in the interface):
UPDATE test.user_purchases
SET inactive = 1
WHERE id IN (
SELECT z.id
FROM (SELECT * FROM test.user_purchases) z
WHERE z.product_id IN (
SELECT product_id
FROM test.products
WHERE product_type IN ("leafblower")
)
AND id NOT IN (
SELECT a.id
FROM (SELECT * FROM test.user_purchases) a
INNER JOIN (
SELECT r.surname, r.email
FROM (SELECT * FROM test.user_purchases) r
JOIN test.products s on r.product_id = s.product_id
WHERE s.product_type IN ("paint")
) b
WHERE a.surname = b.surname
AND a.email = b.email
)
AND id NOT IN (
SELECT MAX(z.id)
FROM (SELECT * FROM test.user_purchases) z
WHERE z.product_id IN (
SELECT product_id
FROM test.products
WHERE product_type IN ("leafblower")
)
AND id NOT IN (
SELECT a.id
FROM (SELECT * FROM test.user_purchases) a
INNER JOIN (
SELECT r.surname, r.email
FROM (SELECT * FROM test.user_purchases) r
JOIN test.products s on r.product_id = s.product_id
WHERE s.product_type IN ("paint")
) b
WHERE a.surname = b.surname
AND a.email = b.email
)
GROUP BY surname, email
)
)
Any suggestions on how I can streamline this query and optimise the speed of it would be much appreciated.
I have three tables.
customer - name,email
history - id,customer_id,attendee_id,date
attendee - name,email
I am trying to fetch the name and email using history table, if the customer_id is -1 then need to get the name and email from the attendee table else from customer table like this :
SELECT * FROM history
left JOIN attendee ON attendee.id = history.attendee_id AND history.customer_id= '-1'
left JOIN customer ON customer.id = history.customer_id AND history.customer_id != '-1'
WHERE history.id = '605';
I can do the same using union all but not using join
the union all code as below
select cus.name,cus.email from histroy
join customer cus on cus.id = history.customer_id and history.customer_id not in ('0','-1')
union all
select cus.name,cus.email from history
join attendee cus on cus.id = history.attendee_id and history.attendee_id not in ('0','-1')
can i write above code using join.
I am having a major problem joining 5 tables because each table only has 1 column in common with only 1 other table.
Here are my tables and columns in each table:
TABLE (COLUMNS)
person (person_id, first_name, last name)
building (building_id, building_name)
room (room_id, room_number, building_id, capacity)
meeting (meeting_id, room_id, meeting_start, meeting_end)
person_meeting (person_id, meeting_id)
OK, now here is what I am trying to do (pasted from a homework assignment):
Construct the SQL statement to find all the meetings that person_id #1 has to attend. Display the following columns:
Person’s first name
Person’s last name
Building name
Room number
Meeting start date and time
Meeting end date and time
Now I know how to join 2 tables but I have no idea how to pull info from 5 different tables like this.
I tried looking up how to do this and it just says to do a UNION command, and I am just learning and have yet to cover that.
As UNION is used to combine the result from multiple SELECT statements into a single result set, you don't need it for this scenario. You have to join all the tables one by one based on their Id.
SELECT P.First_Name, P.Last_Name, B.Building_name, R.Room_Number,
M.Meeting_Start, M.Meeting_End FROM Person P
JOIN Person_Meeting PM ON P.Person_Id = PM.Person_Id
JOIN Meeting M ON PM.Meeting_Id = M.Meeting_Id
JOIN Room R ON M.Room_Id = R.Room_Id
JOIN Building B ON R.Building_Id = B.Building_Id
WHERE P.Person_Id = 1
I have this SQL to fetch a calendar with info about dates.
SELECT h.user_id, name, description, name_day, h.holiday_id, day
FROM calendar_dates d left join calendar_date_holiday h on d.id=h.date_id
left join calendar_holidays hs on h.holiday_id=hs.id
WHERE h.user_id IS NULL
or h.user_id IN (SELECT id FROM calendar_users WHERE username='bd107a66ba')
order by day asc
That works if another user doesn't have a holiday_id for a holiday. Now I'd like to also join holiday ids that have other user_id:s than the condition (´ WHERE h.user_id IS NULL or h.user_id IN ( SELECT id FROM calendar_users WHERE username='bd107a66ba')`) but I don't want the holidays for other users. How can I achieve it?
For example if no user has any own holiday then the result is good
user_id name description name_day holiday_id day
NULL NULL NULL Name NULL 1
...
(30 rows)
If another user than bd107a66ba insert a holiday, then I get only 29 rows since that is not joined. should I use a union? I want a blank holiday if some other user has a holiday on the same day and not the current user.
Think you might be best adding an extra join to the calendar users table (probably an INNER JOIN as I assume the username you are checking must exist on that), then use the user id from that in the join against calendar_date_holiday:-
SELECT h.user_id, name, description, name_day, h.holiday_id, day
FROM calendar_dates d
INNER JOIN calendar_users cu
ON cu.username = 'bd107a66ba'
LEFT JOIN calendar_date_holiday h
ON d.id = h.date_id
AND h.user_id = cu.id
LEFT JOIN calendar_holidays hs
ON h.holiday_id = hs.id
ORDER BY day ASC
I need to write a SQL query to get the patients that have stayed in ALL the hospitals of the city where they live. In one city there may be several hospitals of course.
So for example, if the patient 'xxx' who lives in Washington has been in a hospital, I need to list him only if he's been in all the hospitals of Washington and no less.
This is the structure of the tables:
table patient
patientID
patientCity
table hospital
hospitalCode
hospitalCity
table hospital_stay
hospitalCode
patientID
cityStay
What's the most efficient way to do this for MySQL? Thank you!
Unfortunately, MySQL can't order before grouping, so I had to use subquery to order the result correctly before grouping it.
Have fun :)
SELECT * FROM (
SELECT
p.patientID,
hs.hospitalCode
FROM
patient p
INNER JOIN hospital h ON (p.patientCity = h.hospitalCity)
LEFT JOIN hospital_stay hs ON (p.patientID = hs.patientID AND h.hospitalCode = hs.hospitalCode)
ORDER BY 2
) AS tmp_table
GROUP BY 1
HAVING NOT ISNULL(hospitalCode)
This query should work :
Select p.patientID
, p.patientCity
from patient p
inner join hospital h on h.hospitalCity = p.patientCity
inner join hospital_stay hs on hs.hospitalCode = h.hospitalCode
--where hs.cityStay = 1
group by p.patientID, p.patientCity
having count(*) = (select count(*) from hospital
where hospitalCity = p.patientCity);
Remove the comment if cityStay is kind of a flag that says that the patient went to the hospital.