How to write this SQL query in JPQL - mysql

I'm looking to convert the following SQL into JPQL:
SELECT *
FROM rooms
WHERE NOT EXISTS
(
SELECT *
FROM booking, booking_has_rooms
WHERE rooms.number=booking_has_rooms.rooms_number AND
booking.booking_id=booking_has_rooms.booking_booking_id AND
:date BETWEEN booking.checkin AND booking.checkout
);
So far I have this:
SELECT rooms
FROM Rooms rooms
WHERE NOT EXISTS
(
SELECT bk
FROM Booking b
JOIN b.roomsCollection bk
WHERE :date BETWEEN b.checkin AND b.checkout
)
It returns all the rooms correctly if no bookings are on the specified date.
However if any bookings are on the specified date - it does not return any rooms at all.

You're missing a clause in the inner query:
SELECT rooms
FROM Rooms rooms
WHERE NOT EXISTS
(
SELECT bk
FROM Booking b
JOIN b.roomsCollection bk
WHERE :date BETWEEN b.checkin AND b.checkout
and bk.id = rooms.id
)
Your code would be much clearer if you renamed Rooms to Room. Each instance is a single room, so it should use the singular form.

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;

How to JOIN 2 MySQL tables to determine if joined table has a match

I have 2 MySQL tables (countries) and (reservations)
I want to list every row from countries and simply indicate whether there is a match on reservations or not.
In each instance:
reservations will have 1 matching rows, or
reservations will have many matching rows, or
reservations will have no matching rows
So all I want from the join is to know whether there is a match to reservations or not. Nothing else.
Here is my query statement:
SELECT country.countryID, reservation.citizen
FROM countries AS country
LEFT JOIN (
SELECT reservationID
FROM reservations
LIMIT 1
) AS reservation ON reservation.citizen = country.countryID
ORDER BY reservation.citizen
It fails with Unknown column 'reservation.citizen' in 'on clause'
CONCLUSION:
JOINs cannot solve the problem.
The issue is in the subselect. Notice you have not included the field citizen inside reservation.
SELECT country.countryID, reservation.citizen
FROM countries AS country
LEFT JOIN (
SELECT reservationID, citizen
FROM reservations
LIMIT 1
) AS reservation ON reservation.citizen = country.countryID
ORDER BY reservation.citizen
By the other hand, why are you doing a subselect? And why the limit? Wouldn't be better to just query the following?
SELECT
country.countryID,
count(reservation.reservationID)
FROM
countries AS country
LEFT JOIN reservations AS reservation
ON country.countryID = reservation.citizen
GROUP BY
country.countryID
HAVING
count(reservation.reservationID) > 0
ORDER BY
reservation.citizen
;
You have an issue with the join, it should be like
LEFT JOIN reservations AS reservation ON reservation.citizen = country.countryID
ORDER BY reservation.citizen
OR
LEFT JOIN (
SELECT *
FROM reservations
LIMIT 1
) AS reservation ON reservation.citizen = country.countryID
ORDER BY reservation.citizen
OR better LEFT OUTER JOIN to get rows not matching join conditions.
LEFT OUTER JOIN reservations AS reservation ON reservation.citizen = country.countryID
ORDER BY reservation.citizen

Order By then Group?

I have two tables, the first, hotel_info that has fields such as(hotel_id,hotel_name,location) and a second table rooms, that has room information such as(room_id,room_name,hotel_id,rate,description). I want a query that returns the minimum room rate for a hotel and all information about the hotel from the hotel_info table. So far I have this query that is working properly but its not returning the minimum room rate.
SELECT a.hotel_id,a.hotel_name ,a.location, b.rate FROM hotel_info a
LEFT JOIN rooms b ON b.hotel_id=a.hotel_id
GROUP BY hotel_id
How get the minimum room rate per hotel?
You can use the mysql function min() such as
select a.hotel_id, min(b.rate)
from hotel_info a
left join rooms b on b.hotel_id = a.hotel_id
group by a.hotel_id;
SELECT a.hotel_id, a.hotel_name, a.location, min(b.rate) as min_rate
FROM hotel_info a
LEFT JOIN rooms b ON b.hotel_id = a.hotel_id
GROUP BY a.hotel_id, a.hotel_name, a.location

MySQL subquery on multiple tables

I am trying to retrieve names and address of all guests with bookings for a hotel in London, alphabetically ordered by name in MySQL using subqueries and getting this Error:
Error Code: 1242. Subquery returns more than 1 row
Here's the query that I run:
select * from guest
where guest_no =
(
select guest_no
from booking
where hotel_no = (select hotel_no
from hotel
where city = 'London')
);
and here's the schema for hotel, booking and guest:
hotel (hotel_no, hotel_name, city)
booking (hotel_no, guest_no, date_from, date_to, room_no)
guest (guest_no, g_name, g_address)
additionally, here's the schema for room:
room (room_no, hotel_no, type, price)
Please help me with the above mentioned error and possible solutions.
Thanks and regards.
why not use join as
select
g.guest_no,
g.g_name,
g.g_address
from guest g
inner join booking b on b.guest_no = g.guest_no
inner join hotel h on h.hotel_no = b.hotel_no
where h.city = 'London'
When you use '=', it means that the result of your subquery is exactly 1 row. If you expect multiple results, you need to use the IN keyword, like so:
select * from guest where guest_no IN (select guest_no from booking where hotel_no IN (select hotel_no from hotel where city = 'London'));
EDIT: As #flaschenpost mentions, the performance could be degraded in case there is no proper indexing on the columns involved in the subqueries. You would probably do well to use JOIN rather than such nested subqueries.
Change you query to
select * from guest
where guest_no IN
(select guest_no from booking where hotel_no
IN (select hotel_no from hotel where city = 'London'));
you need joins !
try this !
select a.g_name,a.g_address from guest a inner join booking b on a.guest_no=b.guest_number inner join hotel h on b.hotel_no=h.hotel_no inner join rooms r on b.room_no=h.room_no
where h.city='London'

Can't solve this sql statement to archive my real goal

SELECT hotel.hotel_id, hotel.hotel_name, hotel.hotel_address, hotel.hotel_pic,
room_accommodation.room_full_price
FROM hotel
INNER JOIN room_accommodation ON (room_accommodation.hotel_id = hotel.hotel_id )
INNER JOIN (
SELECT MIN( room_full_price ) AS minPrice
FROM room_accommodation INNER JOIN hotel ON (
hotel.hotel_id =room_accommodation.hotel_id )
WHERE hotel.hotel_address LIKE '%bangkok%'
)room_accommodation ON room_accommodation.room_full_price = room_accommodation.minPrice
This SQL can query each hotel that are in bangkok with a lowest rate of each hotel
But the problem is now I want to query all lowest rate of each hotel but when I cut
the condition where out the result just gave me only one lowest price of all hotel
what wrong and what should I do to archive this
Please Advice
Thank in advance.
This can be greatly simplified - there's no need for a subquery based on the results you need:
SELECT hotel.hotel_id,
hotel.hotel_name,
hotel.hotel_address,
hotel.hotel_pic,
MIN(room_accommodation.room_full_price) as room_full_price
FROM hotel
INNER JOIN room_accommodation
ON room_accommodation.hotel_id = hotel.hotel_id
AND hotel.hotel_address LIKE '%bangkok%'
GROUP BY hotel.hotel_id
Note that for other DBMS's you would need to specify each non-aggregate field in the GROUP BY clause. MySQL lets you get away without that - for better or worse.
i guess u are giving wrong alias to to ur inner query [room_accommodation]
ur query shows that u also have a table with name room_accommodation
SELECT hotel.hotel_id, hotel.hotel_name, hotel.hotel_address, hotel.hotel_pic,
room_accommodation.room_full_price
FROM hotel
INNER JOIN ***room_accommodation*** ON (room_accommodation.hotel_id = hotel.hotel_id )
INNER JOIN (
SELECT MIN( room_full_price ) AS minPrice
FROM room_accommodation INNER JOIN hotel ON (
hotel.hotel_id =room_accommodation.hotel_id )
WHERE hotel.hotel_address LIKE '%bangkok%'
)***room_accommodation*** ON room_accommodation.room_full_price = room_accommodation.minPrice