MySQL Complex Queries - mysql

Hey I've been killing myself trying to figure out how to do these queries. Can someone help me out.
These are the tables I have currently.
BOOKING
HOTEL_NO
GUEST_NO
DATE_FROM
DATE_TO
ROOM_NO
GUEST
GUEST_NO
GUEST_NAME
CITY
ADDRESS
ZIP_CODE
HOTEL
HOTEL_NO
HOTEL_NAME
CITY
ADDRESS
ZIP_CODE
STAR
ROOM
ROOM_NO
HOTEL_NO
ROOM_TYPE
PRICE
And these are the queries I need to do.
-List the guests that have all their bookings (past and present) in the same hotel.
-Create a view VIP-Guest that lists guests who have reservations for only 4 star hotels or
4 star hotels
-Among the VIPs find the guest with the largest total stay (in term of number of days).
Express this as a query with the view and without the view
Can someone help me out?

this should get you started. to post on stackoverflow, you need to come with specific questions or errors or problems. like for the query you posted in the comments up top.... that could be a question in itself: "I have these tables, this one specific goal (question/result set), and I tried this query... it gives me this result or it gives me this error."
BOOKING: HOTEL_NO, GUEST_NO, DATE_FROM, DATE_TO, ROOM_NO
GUEST: GUEST_NO, GUEST_NAME, CITY, ADDRESS, ZIP_CODE
HOTEL: HOTEL_NO, HOTEL_NAME, CITY, ADDRESS, ZIP_CODE, STAR
ROOM: ROOM_NO, HOTEL_NO, ROOM_TYPE, PRICE
all guests and bookings...
-- all guests: select * from guest;
-- all bookings: select * from booking;
select *
from guest
join booking on guest.guest_no = booking.guest_no;
-- which is the same as...
select *
from guest, booking
where guest.guest_no = booking.guest_no;
-- and... your comments query was missing a group by clause
select guest_no, guest_name, count(*) as booking_count
from guest
join booking on guest.guest_no = booking.guest_no
group by guest_no, guest_name;
select guest_no, guest_name, count(distinct hotel_no) as hotel_count
from guest
join booking on guest.guest_no = booking.guest_no
group by guest_no, guest_name
having count(distinct hotel_no) = 1;
and I count(distinct hotel_no) because... they might have 3 bookings at Hotel A and 1 at Hotel B. The basic join would give me 4 rows for that person. I don't care how many bookings. I care how many hotels. So I want to count the distinct occurrences of hotel_no per person (there's that group by) instead of every row.
guests by their stars...
-- so we have to get guest and hotel joined. bc hotel has stars.
-- booking has hotel_no. so... we can use that last query and
-- join in HOTEL to get the star information. in the WHERE you
-- will want to put your filter for the number of stars that you
-- are looking for =4 or >=4 or something like that.
-- you might want to check out DISTINCT to get just a list of names
-- instead of a row for each booking.
number of days they stayed...
-- use the second query.
-- datediff(date_to, date_from) as days_stay gives you the length of stay
-- i don't know what the view is.
-- to get the top length could go two ways... either ORDER BY and LIMIT if there is
-- only one person with the top length (let's say 10 days). if there are many people
-- who have stayed 10 days, you'll need to do a MAX on the days_stay and either join
-- that in or use it in the WHERE as a nested select.
this assumes there is a single highest length of stay. only one person stayed 10 days.
SELECT guest_no, guest_name, datediff(date_to, date_from) days_stayed
FROM vip_guest
join booking on vip_guest.guest_no = booking.guest_no
order by datediff(date_to, date_from) desc
limit 1,1
this should work for many... (i'm not testing these... just kind of looking at it)
SELECT distinct guest_no, guest_name, datediff(date_to, date_from) max_stay
FROM vip_guest
join booking on vip_guest.guest_no = booking.guest_no
where datediff(date_to, date_from) = (
select max(datediff(date_to, date_from)) as days_stayed
from booking )
the nested query gets the maximum stay length of everyone. vip_guest and bookings joined together give us guest and date imfo. we will get all bookings for every vip_guest. so we want to filter it down to where stay lengths == the max stay length. in case a person had multiple 10 day stays (my arbitrary max stay length)... use distinct.
now... thats a good point about the nested query. i don't know what is in your view. it is possible none of the max vip guests had a stay as long as the max stay length. in that case, this query would return nothing.

Related

Grouping in my SQL for a constraint less than 10

I am confused on which table I should use and or should I join the tables when attempting this question?
List total number of hotels in the database that have less than 10 rooms.
Hotel (hotelNo, hotelName, city)
Room (roomNo, hotelNo, type, price)
Booking (hotelNo, guestNo, dateFrom, dateTo, roomNo)
Guest (guestNo, guestName, guestAddress)
I have tried by just useing one table Room in my statement
SELECT hotelNo
FROM Room
WHERE roomNo < 10
GROUP BY hotelNo;
Would this be correct or should I use something like this?
SELECT h.hotelNo,r.roomNo
FROM Hotel h JOIN Room r ON h.hotelNo= r.hotelNo
WHERE r.roomNo < 10
GROUP BY hotelNo;
Assuming that all hotels have at least one room, you don't need a join. But, you do need aggregation:
select count(*)
from (select r.hotelno
from rooms r
group by r.hotelno
having count(*) < 10
) r;
The subquery returns the hotels that have fewer than 10 rooms (and are in the rooms table, so they have at least one room).
The outer query counts the number of such hotels.
Check count on the having in order to be applied to the groups, and that count the number of rows returned by that query
SELECT COUNT(*)
FROM (
SELECT hotelRo
FROM Room
GROUP BY hotelNo
HAVING COUNT(*)<10
) AS TMP;

Want to count occurrence, then only print count values which are higher than the average of all counted values

So, I was trying to count the number of times a patient went to the hospital for each of the available 10 patients (including those who does not went at all, for no good reason), but only wanting to print the ones whose visit count is higher than the average of all recorded visit counts.
How can I do this, when I can't compare any count values in the WHERE and HAVING clauses, and can't precalculate the average first the compare to it later). Please help
My guess is you're looking for something like :
SELECT
patientid,
count(*)
FROM visits
GROUP BY patientid
HAVING count(*) >
(SELECT AVG(ct) FROM
(SELECT count(*) ct FROM visits GROUP BY patientid) x
)
Visits might have to be upgraded to a left join between patient (on the left) and visits if there are patients who have never visited and you want their zeros to influence the average

Determine total cost per user from 3 Different Tables

I am working on a theatre booking system in MySql (My first SQL project). I have three tables:
Production (contains Title, BasicTicketPrice),
Performance (PerformanceDate, PerformanceTime, Title)
Booking (Email of person who booked, PerformanceDate, PerformanceTime, RowNumber).
Each person booked tickets for two or three performances (using their email to book).
I need to to write a query which will display the prices paid for all booked seats and I need to output the RowNumber, Email of person who booked and the Calculated Price.
I understand that I need to join these tables and make the query display a temporary column called Calculated Price but I don't know how to calculate the price.
I tried this:
SELECT DISTINCT b.RowNumber, b.Email, pr.BasicTicketPrice
FROM booking b, production pr performance p
WHERE p.Title=b.PerfDate*b.PerfTime*b.RowNumber;
SELECT CONCAT (PerfDate, PerfTime, RowNumber) AS BookingID FROM booking;
SELECT RowNumber, Email, CONCAT(PerfDate, PerfTime, RowNumber) AS BookingID FROM booking;
SELECT RowNumber, Email, CONCAT((CONCAT(PerfDate, PerfTime, RowNumber) AS BookingID
FROM booking)BasicTicketPrice*BookingID);
SELECT RowNumber, Email, CONCAT(PerfDate, PerfTime, RowNumber) AS BookingID INTEGER
FROM booking;
SELECT RowNumber FROM booking
LEFT JOIN (SELECT Title FROM performance WHERE '2017-11-01 19:00:00' Email IS NULL);
But it didn't work.
Any suggestions? I will be grateful for any ideas.
Assuming:
One row in Bookings per booked seat
Title to be a suitable primary key for Production
PerformanceDate, PerformanceTime to be a suitable primary composite key for Performance
You'll be looking to join the three tables together as per the keys assumed above. It seems you wish to group the bookings together per performance, by the person booking the tickets - if so, you'll need to use an aggregate to show the seat numbers (I've used GROUP_CONCAT to delimit them), as well as to COUNT the tickets purchased and multiply by the ticket cost.
SELECT
b.Email, prod.Title, per.PerformanceDate, per.PerformanceTime,
GROUP_CONCAT(RowNumber) AS BookedSeats,
COUNT(RowNumber) * prod.BasicTicketPrice AS TotalCost
FROM Booking b
INNER JOIN Performance per
ON b.PerformanceDate = per.PerformanceDate
AND b.PerformanceTime = per.PerformanceTime
INNER JOIN Production prod
ON per.Title = prod.Title
GROUP BY
b.Email, prod.Title, per.PerformanceDate, per.PerformanceTime, prod.BasicTicketPrice
ORDER BY prod.Title, per.PerformanceDate, per.PerformanceTime;
Technically, we should include all non-aggregated columns in the GROUP BY, hence prod.BasicTicketPrice is listed as well.

How to sum total bookings for a particular flight

Ok so i have two columns in a table. One of these says how many people the customer booked to go to a particular country.
The other column shows which country the order was booked for, for example, fiji, australia.
Im having trouble adding up the No_Of_People column in order to determine which flight destination has the most people going to it.
If there was only one booking per country this would be easy, as it would be something like:
select destination_name from bookings order by sum(No_Of_People) desc limit 1;
Just wondering how i can do this, knowing that there are multiple people booking for the same country.
You need to group by destination to get the people per destination:
SELECT
destination_name,
sum(No_Of_People) AS count
FROM
bookings
GROUP BY destination_name
ORDER BY count desc;
https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html
select sum(No_Of_People), destination_name from bookings group by destination_name order by sum(No_Of_People) desc

Query to find how many purchases were made this year, For each Artist

I need to list the Artist's Id_no, last name (lname) and how any purchases have been made on their releases this year. The only information about the purchases is different purchase dates.
My code so far :
SELECT id_no, lname, purchasedate AS num_ops
FROM Artist JOIN Sales ON Artist.id_no = Sales.artist
WHERE DATE_SUB(CURDATE(),INTERVAL 1 YEAR) <= purchasedate
However this only returns the Id_no's who have made sales, and I need all even if it is 0. On distrinctl name, and num_ops is a date of their first purchasedate. I need to alter this code to list how many purchases they have been involved in within this year. I've tried using COUNT(purchasedate) however this just returns one row. I wish the returning table to return:
1st Column: The Artist's ID Number
2nd Column: The Aritist's Last Name
3rd Column: The number of people who have purchased their CD's (which is a count of purchasedate)
I am struggling with the 3rd column majorly, and any help would be greatly appriciated.
You need:
a left join
to move the date condition into the ON clause of the JOIN
use the count(*) aggregating function
Like this:
SELECT id_no, lname, count(purchasedate) as num_ops
FROM Artist
LEFT JOIN Sales ON Artist.id_no = Sales.artist
AND DATE_SUB(CURDATE(),INTERVAL 1 YEAR) <= purchasedate
GROUP BY id_no, lname
The LEFT JOIN will ensure a row is returned for every artist even if there are no sales
By moving the date condition into the join that will still return a row for every artist even if there's no sale for the year. If the condition is left in the WHERE clause, that would filter out artists that didn't make sales in the last year.
A key point here is that the join condition may contain conditions unrelated to the keys involved - that's how you get conditional joins, which is what you want here to make the left join still function correctly