How to get count of customers? - sql

I need some help with an SQL query.
Let's say we have this sample database which manages Bookings in a hotel:
Customer(ID, name, birthDate, city);
Room(number, floor, beds, roomtype, price);
Bookings(Customer, roomNumber, floor, checkInDate, checkOutDate);
I need to know which customers booked only and ONLY economic type of rooms.
This is my query:
select Customer from Bookings
join Room on(Bookings.num = camera.roomNumber and Bookings.floor=
Room.floor)
where (Bookings.Customer, Bookings.floor) not in (select number, floor from
Room where roomType != 'economic')
My issue is that this query shows me customers which booked economic rooms, but it also shows me customers which booked other type of rooms.
How can I restrict the output in order to get Customers which booked ONLY economic rooms?
Thank you

Use not exists :
select c.*
from Customer c
where not exists (select 1
from Bookings b
inner join Room r on b.num = r.roomNumber and b.floor = r.floor
where c.ID = b.Customer and r.roomType <> 'economic'
);

You can use aggregation:
select b.Customer
from Bookings b join
Room r
on b.num = r.roomNumber and b.floor = r.floor
group by b.Customer
having min(roomType) = max(roomType) and min(roomType) = 'economic';

Related

What is the valid SQL query for the following JOIN problem

I have the following tables
Customer (CID, name, address)
Orders (CID, BID, onDate, quantity)
Device (DID, title, IMEI, price, MID)
Manufacturer (MID, name, address)
What SQL statement would allow me to retrieve the ID's and names of all
the customers who have spent atleast X amount (lets say 350 for example)
on devices made my the manufacturer "Sony". The list should include the total amount of money spent by each customer on those devices.
I assume that the table Orders contains a column DID (BID is a typo, right?) that relates it to the table device.
Join the tables, group by customer to aggregate and set the condition in the HAVING clause:
select c.CID, c.name,
sum(o.quantity * d.price) total_amount
from customer c
inner join orders o on o.CID = c.CID
inner join device d on d.DID = o.DID
inner join manufacturer m on m.MID = d.MID
where m.name = 'Sony'
group by c.CID, c.name
having sum(o.quantity * d.price) >= 350

sql 3 tables sum

I have 3 tables, bookings, companies and flights. bookings has no_seats andseat_price. I need to calculate sum of no_seats * seat_price for each company (for all their flights together). flight has company_id and booking has flight_id. What's the best way to do that?
Assuming "companies" has a 1-to-many relation with "flights" and "flights" have 1-to-many relation with "bookings":
select c.CompanyName, sum(b.no_seats * b.seat_price) as total
from Companies c
inner join Flights f on f.Company_Id = c.Company_id
inner join Bookings b on b.Flight_ID = f.Flight_ID
group by c.Company_ID, c.CompanyName;
Your question doesn't provide enough informations, but I guess this is what you want ?
Select C.Company_Id, SUM( B.no_seats * B.seat_price) as [Desired Calculation]
From Company C, Flights F, Bookings B
Where C.Company_Id = F.Company_Id
And F.Flight_Id = B.Flight_Id
Group By C.Company_Id
If there are any further questions please feel free to ask.

Please help this SQL query

Tables:
Doctor(doctor_id, name, address, tel, specialty)
Patient(patient_id, name, numsecu, doctor_reference)
Visit(doctor, patient, date_visit)
The question is show the patients who have seen every specialty doctors.
I do this way but I don't know how to check that the patients have seen every specialty doctors.
select distinct p.nom, m.specialite
from patient p, visite v, medecin m
where p.patient_id = v.patient
and v.medecin = m.medecin_id
group by p.nom, m.specialite
Made a bit of an assumption here that "specialty doctors" are identified by a non-null specialite column in the medecin table.
EDIT: Added JOIN to medecin in the main query to filter the visits to only specialty doctors.
SELECT p.nom
FROM patient p
INNER JOIN visite v
ON p.patient_id = v.patient
INNER JOIN medicin m
ON v.medecin = m.medecin_id
WHERE m.specialite IS NOT NULL
GROUP BY p.nom
HAVING COUNT(DISTINCT m.medecin_id) = (SELECT COUNT(*)
FROM medecin
WHERE specialite IS NOT NULL)

SQL Query Issue - Natural Join and table naming

I'm running into some difficulty with a query for my databases class. Given the following schema:
Customers (customerid, first_name, last_name, address, city, state, phone, status)
Branches (branchno, address, city, state, phone, manager_name)
Employees (empno, firstname, lastname, address, city, state, phone, emergency_contact, title, managerno)
Rooms (roomno, branchno, price, bed_size)
Bookings (roomno, branchno, customerid, checkin_date, checkout_date, empno)
I'd like to find the customer(s) that have rented the most expensive room. I gave this query a try...
SELECT customerid FROM bookings NATURAL JOIN rooms
EXCEPT
(SELECT customerid FROM (bookings NATURAL JOIN rooms) AS S, (bookings NATURAL JOIN
rooms) as T WHERE S.price < T.price)
The problem comes from the way I want to rename the tables. I'd like to use the natural join of bookings and rooms as components of the Cartesian product... How can I do this?
Thank you very much.
You could use this:
SELECT
customerid
FROM
Bookings
NATURAL JOIN
Rooms
NATURAL JOIN
( SELECT MAX(price) AS price
FROM Rooms
) AS MostExpensiveRoom
Your query seems valid, except that you need to clarify which customerid you want in the second subquery, the S. or the T. one. The comma , syntax means a CROSS JOIN between S and T so you have two customerids:
(SELECT customerid FROM bookings NATURAL JOIN rooms)
EXCEPT
(SELECT S.customerid
FROM
(bookings NATURAL JOIN rooms) AS S
CROSS JOIN
(bookings NATURAL JOIN rooms) AS T
WHERE S.price < T.price
)
SELECT * FROM customers as c
INNER JOIN bookings as b ON b.customerid = c.customerid
INNER JOIN rooms as r ON r.roomno = b.roomno
ORDER BY r.price DESC
LIMIT 1;
if you want only the names, or specified fields, you can use GROUP BY.
This query do the same (if the previous is good syntactically):
SELECT * FROM customers,bookings,rooms
WHERE bookings.customerid = customers.customerid
AND rooms.roomno = bookings.roomno
ORDER BY rooms.price DESC
LIMIT 1
so if you want id-s and names ordered by rent price desc:
SELECT customers.customerid, customers.fistname, customers.lastname FROM
customers,bookings,rooms
WHERE bookings.customerid = customers.customerid
AND rooms.roomno = bookings.roomno
ORDER BY rooms.price DESC
GROUP BY customers.customerid, customers.fistname, customers.lastname
LIMIT 10

SQL query assistance

I have this schema:
Hotel (**hotelNo**, hotelName, city)
Room (**roomNo, hotelNo**, type, price)
Booking (**hotelNo, guestNo, dateFrom**, dateTo, roomNo)
Guest (**guestNo**, guestName, guestAddress)
** denotes primary keys
I have to complete this query:
Display each hotel and its most common room.
I have this query, which isn't quite correct:
SELECT r.hotelno, type, count(*)
FROM Hotel h, room r
WHERE h.hotelNo = r.hotelno
GROUP BY r.hotelNo, type;
This is what it outputs:
What am I doing wrong?
It looks as though you're seeking the type of room which has maximum number of bookings for rooms of a given type at each hotel - an aggregate (maximum) of another aggregate (count of bookings of room type).
Build it up piece-wise. The number of bookings of rooms of each type at each hotel:
SELECT r.hotelno, r.type, count(*) AS num_bookings
FROM Booking AS b
JOIN Room AS r ON b.hotelNo = r.hotelno AND b.roomNo = r.roomNo
GROUP BY r.hotelNo, r.type;
Now, you need to know which room type has the maximum at each hotel. That has to be done in two stages:
Find the maximum number of bookings at the hotel for any type.
Find the room types with that maximum number.
The first stage is:
SELECT s.hotelno, MAX(num_bookings) AS max_bookings
FROM (SELECT r.hotelno, r.type, count(*) AS num_bookings
FROM Booking AS b
JOIN Room AS r ON b.hotelNo = r.hotelno AND b.roomNo = r.roomNo
GROUP BY r.hotelNo, r.type
) AS s
GROUP BY s.hotelno;
The second stage uses both the previous results for a final answer:
SELECT t.hotelno, t.type
FROM (SELECT r.hotelno, r.type, count(*) AS num_bookings
FROM Booking AS b
JOIN Room AS r ON b.hotelNo = r.hotelno AND b.roomNo = r.roomNo
GROUP BY r.hotelNo, r.type) AS t
JOIN (SELECT s.hotelno, MAX(num_bookings) AS max_bookings
FROM (SELECT r.hotelno, r.type, count(*) AS num_bookings
FROM Booking AS b
JOIN Room AS r ON b.hotelNo = r.hotelno AND b.roomNo = r.roomNo
GROUP BY r.hotelNo, r.type
) AS s
GROUP BY s.hotelno) AS m
ON t.hotelno = m.hotelno AND t.num_bookings = m.max_bookings;
If your DBMS supports WITH clauses, you can write that more succinctly.
If you are looking for popularity, you would need to take into account the Booking table. Add the Booking table to your FROM statement, link on hotelNo and roomNo and do a count on the Booking table. This should give you the counts you want.
Edit:
Here is some sample code for you (tested):
SELECT TOP (100) PERCENT dbo.Hotel.hotelName, dbo.Room.type, COUNT(*) AS Count
FROM dbo.Booking INNER JOIN
dbo.Room ON dbo.Booking.roomNo = dbo.Room.roomNo AND dbo.Booking.hotelNo = dbo.Room.hotelNo
INNER JOIN dbo.Hotel ON dbo.Room.hotelNo = dbo.Hotel.hotelNo
GROUP BY dbo.Hotel.hotelName, dbo.Room.type
ORDER BY Count DESC
I think you're going to have to use an inner query to get this one working:
SELECT dbo.Hotel.hotelName, pop.type, pop.Count
FROM dbo.Hotel
INNER JOIN (
SELECT TOP 1 dbo.Hotel.hotelNo, dbo.Room.type, COUNT(*) AS Count
FROM dbo.Hotel
INNER JOIN dbo.Room ON dbo.Room.hotelNo = dbo.Hotel.hotelNo
INNER JOIN dbo.Booking ON dbo.Booking.roomNo = dbo.Room.roomNo AND dbo.Booking.hotelNo = dbo.Hotel.hotelNo
GROUP BY dbo.Hotel.hotelNo, dbo.Room.type
ORDER BY Count DESC, dbo.Room.type
) AS pop ON pop.hotelNo = dbo.Hotel.HotelNo
ORDER BY dbo.Hotel.hotelName