Why is mysql saying there is a syntax error? - mysql

I'm pretty new to the world of outer joins, and I'm trying to get used to them, but I have no idea why mysql is saying the syntax is incorrect. Does anyone care to give some insight?
SELECT * FROM user_courses, course_updates
WHERE user_courses.crn = course_updates.crn AND user_courses.user_id = 1
LEFT JOIN followers ON (followers.followee = course_updates.user_id)

The LEFT JOIN clause should become before the WHERE clause.
SELECT * FROM user_courses, course_updates
LEFT JOIN followers ON (followers.followee = course_updates.user_id)
WHERE user_courses.crn = course_updates.crn AND user_courses.user_id = 1
By the way, you can also use `INNER JOIN for you other tables, so you don't have two types of syntax:
SELECT * FROM user_courses
INNER JOIN course_updates on user_courses.crn = course_updates.crn
LEFT JOIN followers ON followers.followee = course_updates.user_id
WHERE user_courses.user_id = 1
Note that I have omitted the parentheses around the ON condition, which is perfectly valid. Also, you can see that using INNER JOIN, you can specify the join conditions in the join itself, leaving the WHERE clause solely for filtering. I think this results in better readability of your query.

Use like this
SELECT * FROM user_courses, course_updates
LEFT JOIN followers ON (followers.followee = course_updates.user_id)
WHERE user_courses.crn = course_updates.crn AND user_courses.user_id = 1

Because there is a syntax error.
Try
SELECT *
FROM user_courses LEFT JOIN
course_updates ON user_courses.crn = course_updates.crn
AND user_courses.user_id = 1 LEFT JOIN
followers ON (followers.followee = course_updates.user_id)
From enter link description here
the FROM table_references comes before the WHERE where_condition
Also maybe look at JOIN Syntax

Try This..
SELECT * FROM user_courses INNER JOIN course_updates ON user_courses.crn = course_updates.crn LEFT JOIN followers ON followers.followee = course_updates.user_id WHERE user_courses.user_id = 1
Since, WHERE clause will be used after JOIN

Yes your syntax is wrong, in your case use WHERE clause at the end of the statement as follows:
SELECT *
FROM user_courses uc
INNER JOIN course_updates cu ON cu.crn = uc.crn
LEFT OUTER JOIN followers f ON f.followee = cu.USER_ID
WHERE uc.USER_ID = 1
Also make sure f.followee type and cu.USER_ID are the same.
Hope this would help you!!!

Related

Using SUM function in an update query with inner joins

Getting an error when running this
UPDATE FlightBooking
INNER JOIN Passenger ON Passenger.FlightBookingId=FlightBooking.FlightBookingId
INNER JOIN AirplaneSeat ON AirplaneSeat.AirplaneSeatId = Passenger.SeatId
INNER JOIN Section ON AirplaneSeat.SectionId = Section.SectionId
INNER JOIN ExtraCost ON ExtraCost.FlightBookingId=FlightBooking.FlightBookingId
INNER JOIN Luggage ON Luggage.LuggageId = ExtraCost.LuggageId
INNER JOIN SportsEquipment ON ExtraCost.SportsEquipmentId=SportsEquipment.SportsEquipmentId
INNER JOIN Insurance ON ExtraCost.InsuranceId = Insurance.InsuranceId
INNER JOIN CarHirePrice ON CarHirePrice.CarHirePriceId= ExtraCost.CarHirePriceId
INNER JOIN Route ON FlightBooking.RouteId = Route.RouteId
SET FlightBooking.TotalCost = (SUM(Section.PriceInflux+Route.RoutePrice+Luggage.Price+SportsEquipment.SportsEquipmentPrice+Insurance.Price+CarHirePrice.TotalPrice))
WHERE FlightBooking.FlightBookingId=1;
When I have it formed as a Select query it returns the correct value so all the tables are fine. I'm assuming my syntax is wrong.
Any help would be appreciated.
You should use the following syntax when using an aggregate in an update statement.
UPDATE t1
SET t1.field = t2.field2Sum
FROM table1 t1
INNER JOIN (select field3, sum(field2) as field2Sum
from table2
group by field3) as t2
on t2.field3 = t1.field3
See Below, I only scripted a few tables but you can see how to do the rest.
UPDATE FlightBooking set TotalCost = (ExtraCost.SumExtra + SumLuggage) From FlightBooking
INNER JOIN Passenger ON Passenger.FlightBookingId=FlightBooking.FlightBookingId
INNER JOIN AirplaneSeat ON AirplaneSeat.AirplaneSeatId = Passenger.SeatId
INNER JOIN Section ON AirplaneSeat.SectionId = Section.SectionId
INNER JOIN (Select FlightBookingId, sum(ExtraCost) as SumExtra from Extracost Group by FlightBookingId) as ExtraCost
ON ExtraCost.FlightBookingId=FlightBooking.FlightBookingId
INNER JOIN (Select FlightBookingId, sum(Price) as SumLuggage from Luggage Group by FlightBookingId) as Luggage
ON Luggage.FlightBookingId=FlightBooking.FlightBookingId
Are you sure that you have multiple records that match a single booking id?
If not, you can dispense with the sum():
SET FlightBooking.TotalCost = (Section.PriceInflux+Route.RoutePrice+Luggage.Price+SportsEquipment.SportsEquipmentPrice+Insurance.Price+CarHirePrice.TotalPrice)
If not, you'll need to pre-aggregate the tables that could generate multiple rows. In fact, you need to do this anyway to get a valid result (Cartesian products generated by joins will throw off the over sum).
many different possibilities for using aggregate funtion with update and inner join
UPDATE flight
SET flight.TotalCost = t.sumPrice
FROM FlightBooking AS flight
INNER JOIN
(
SELECT SUM(Section.PriceInflux+Route.RoutePrice+Luggage.Price+SportsEquipment.SportsEquipmentPrice+Insurance.Price+CarHirePrice.TotalPrice)) as sumPrice
FROM Passenger ON Passenger.FlightBookingId=flight.FlightBookingId
INNER JOIN AirplaneSeat ON AirplaneSeat.AirplaneSeatId = Passenger.SeatId
INNER JOIN Section ON AirplaneSeat.SectionId = Section.SectionId
INNER JOIN ExtraCost ON ExtraCost.FlightBookingId=flight.FlightBookingId
INNER JOIN Luggage ON Luggage.LuggageId = ExtraCost.LuggageId
INNER JOIN SportsEquipment ON ExtraCost.SportsEquipmentId=SportsEquipment.SportsEquipmentId
INNER JOIN Insurance ON ExtraCost.InsuranceId = Insurance.InsuranceId
INNER JOIN CarHirePrice ON CarHirePrice.CarHirePriceId= ExtraCost.CarHirePriceId
INNER JOIN Route ON flight.RouteId = Route.RouteId
) t
WHERE flight.bookingID = 1
also have a look to this examples
PC #PauloSantos and #OMGPonieshttps://stackoverflow.com/a/2009981/4426282

Count matched words from IN operator

i have this little mysql query :
select t.title FROM title t
inner join movie_keyword mk on mk.movie_id = t.id
inner join keyword k on k.id = mk.keyword_id
where k.keyword IN (
select k.keyword
FROM title t
inner join movie_keyword mk on mk.movie_id = t.id
inner join keyword k on k.id = mk.keyword_id
where t.id = 166282
)
LIMIT 15
as you can see it will return all titles from title that have at least one the same keyword that have movie with id 166282.
Now i have problem, because i want also count how many keywords was matched in IN operator(let's say i want to see only titles that have 3 or more the same keywords), i tried something with aggregate functions, but everything failed, so i came here with my problem. Maybe somebody can give me some advice, or code example.
I'm not also sure, if this "subquery way" is good, so if there are some better options how i should solve my problem, I am open to any suggestions or tips.
Thank you!
#Edit
So after some problems, i have one more. This is my current query :
SELECT s.title,s.vote,s.rating,count(dk.key) as keywordCnt, count(dg.name) as genreCnt
FROM series s
INNER JOIN series_has_genre shg ON shg.series_id = s.id
INNER JOIN dict_genre dg ON dg.id = shg.dict_genre_id
INNER JOIN series_has_keyword shk ON shk.series_id = s.id
INNER JOIN dict_keyword dk ON dk.id = shk.dict_keyword_id
WHERE dk.key IN (
SELECT dki.key FROM series si
INNER JOIN series_has_keyword shki ON shki.series_id = si.id
INNER JOIN dict_keyword dki ON dki.id = shki.dict_keyword_id
WHERE si.title LIKE 'The Wire'
)
and dg.name IN (
SELECT dgo.name FROM series so
INNER JOIN series_has_genre shgo ON shgo.series_id = so.id
INNER JOIN dict_genre dgo ON dgo.id = shgo.dict_genre_id
WHERE so.title LIKE 'The Wire'
)
and s.production_year > 2000
GROUP BY s.title
ORDER BY s.vote DESC, keywordCnt DESC ,s.rating DESC, genreCnt DESC
LIMIT 5
Problem is, it is very, very, very slow. Any tips what i should change, to run it faster ?
Will this work for you:
select t.title, count(k.keyword) as keywordCount FROM title t
inner join movie_keyword mk on mk.movie_id = t.id
inner join keyword k on k.id = mk.keyword_id
where k.keyword IN (
select ki.keyword
FROM title ti
inner join movie_keyword mki on mki.movie_id = ti.id
inner join keyword ki on ki.id = mki.keyword_id
where ti.id = 166282
) group by t.title
LIMIT 15
Note that I have changed the table names inside the nested query to avoid confusion.

MySQL - Return everyone who doesn't have booking?

I'm trying to get MySQL to return me all instructors who don't have a booking at a certain time. This query is essentially the search query. So return all instructors and their details that aren't already booked basically. Could someone help me finish it off?
SELECT
AddressTypes.AddressTypeName,
Addresses.*,
InstructorSettings.*,
Users.*,
BookedSlots.DateTime
FROM Users
LEFT OUTER JOIN InstructorSettings
ON Users.UserID = InstructorSettings.UserID
LEFT OUTER JOIN Addresses
ON Users.UserID = Addresses.UserID
INNER JOIN AddressTypes
ON Addresses.AddressTypeID = AddressTypes.AddressTypeID
LEFT OUTER JOIN BookedSlots
ON Users.UserID = BookedSlots.UserID
WHERE Users.AccountTYpe = 3 AND Addresses.PostCode1 IN ('l13') AND BookedSlots.DateTime <> '2013-04-25 11:00:00'
The query above doesn't return anything, but if I take out the "AND BookedSlots.DateTime <> '2013-04-25 11:00:00'" it returns all the instructors details fine.
Database
It looks to me as if what you're looking for is the lack of existence of records in BookedSlots for the specified time.
I'm not sure if this is considered MySQL best practices, but I typically accomplish that task not with a join, but with a sub-select or a temp table, like so:
SELECT
AddressTypes.AddressTypeName,
Addresses.*,
InstructorSettings.*,
Users.*,
FROM Users
LEFT OUTER JOIN InstructorSettings
ON Users.UserID = InstructorSettings.UserID
LEFT OUTER JOIN Addresses
ON Users.UserID = Addresses.UserID
INNER JOIN AddressTypes
ON Addresses.AddressTypeID = AddressTypes.AddressTypeID
WHERE Users.AccountType = 3 AND Addresses.PostCode1 IN ('l13')
AND Users.UserID not in (SELECT BookedSlots.InstructorID FROM BookedSlots
WHERE BookedSlots.DateTime = '2013-04-25 11:00:00')
EDIT: per comments, changed the select statement to disclude BookedSlots, and the sub-select to return InstructorId (which matches instructors instead of students on the booking).
To check that there aren't any bookings on a particular timeslot, include the timeslot in the join conditions and select where the timeslot id is null - like so:
SELECT
AddressTypes.AddressTypeName,
Addresses.*,
InstructorSettings.*,
Users.*,
BookedSlots.DateTime
FROM Users
LEFT OUTER JOIN InstructorSettings
ON Users.UserID = InstructorSettings.UserID
LEFT OUTER JOIN Addresses
ON Users.UserID = Addresses.UserID
INNER JOIN AddressTypes
ON Addresses.AddressTypeID = AddressTypes.AddressTypeID
LEFT OUTER JOIN BookedSlots
ON Users.UserID = BookedSlots.UserID AND
BookedSlots.DateTime = '2013-04-25 11:00:00'
WHERE Users.AccountTYpe = 3 AND
Addresses.PostCode1 IN ('l13') AND
BookedSlots.UserID is null

SQl queries left join not giving accurate results

I have been trying to join two tables (USERS AND USERS_ROLES) based on their role id I put the left join on following query
users.id = users_roles.fk_user_id
but the output is not correct of users_roles.fk_role_id coulmun and shows NULL where it should display the id of users.id = users_roles.fk_user_id that is 4 (at most places) because on users.id = users_roles.fk_user_id the value of users_roles.fk_role_id = 4
Kindly let me know how can i fix that so my query should result the exact vlaues of ids where they match,
Thanks
SELECT users.id, users.v_first_name, users.v_last_name, user_facility.fk_facility_id,users.fk_tenant_id, marital_status.v_marital_status,
users.v_blood_type, NOW(),users_roles.fk_role_id
FROM users
LEFT JOIN (user_facility, marital_status, users_roles) ON
users.id = user_facility.fk_user_id AND users.fk_marital_status_id=marital_status.id AND users.id = users_roles.fk_user_id
Usage of AND operator when used with Left or Right join gives different result. You should be clear what you are trying to accomplish..See this
well it is what you get by first implicitly inner-joining 3 tables and then explicitly left-joining the result to a 4th table only if 3 conditions relevant to all of the 3 inner-joinded tables are matched (i.e. when 3rd condition is false, nothing is joined from either of the 2 remaining tables)
i strongly suggest not to combine implicit and explicit joins, i personally use explicit joins all the time:
if you need an outer join:
SELECT ...
FROM users
LEFT JOIN user_facility ON users.id = user_facility.fk_user_id
LEFT JOIN marital_status ON users.fk_marital_status_id=marital_status.id
LEFT JOIN users_roles ON users.id = users_roles.fk_user_id
if you need an inner join:
SELECT ...
FROM users
JOIN user_facility ON users.id = user_facility.fk_user_id
JOIN marital_status ON users.fk_marital_status_id=marital_status.id
JOIN users_roles ON users.id = users_roles.fk_user_id
or if you prefere implicit inner joins for some obscure reason:
SELECT ...
FROM users,
user_facility,
marital_status,
users_roles
WHERE users.id = user_facility.fk_user_id
AND users.fk_marital_status_id=marital_status.id
AND users.id = users_roles.fk_user_id
(implicit outer joins are getting deprecated in all RDBMS as far as i know)
When it shows NULL it means there isn't a correspondency (relation) between all tables in the JOIN clause.
If you want to show only the ones that have relations in all tables, use INNER JOIN instead.
SELECT u.id,
u.v_first_name,
u.v_last_name,
uf.fk_facility_id,
u.fk_tenant_id,
ms.v_marital_status,
u.v_blood_type,
NOW(),
ur.fk_role_id
FROM users u
INNER JOIN user_facility uf ON u.id = uf.fk_user_id
INNER JOIN marital_status ms ON u.fk_marital_status_id=ms.id
INNER JOIN users_roles ur ON u.id = ur.fk_user_id

MySQL Not unique table/alias

I looked at the answers of others having the same problem, but I can't figure out how to fix the "Not unique table/alias".
SELECT m.*, u.*
FROM ".TABLE_PREFIX."users_medals u
LEFT JOIN ".TABLE_PREFIX."medals m ON u.medal_id = m.medal_id
WHERE u.user_id IN (".$post['uid'].")
AND m.medal_level = (
SELECT MAX(".TABLE_PREFIX."medals.medal_level) FROM ".TABLE_PREFIX."medals
LEFT JOIN ".TABLE_PREFIX."medals ON ".TABLE_PREFIX."users_medals.medal_id = ".TABLE_PREFIX."medals.medal_id
WHERE ".TABLE_PREFIX."users_medals.user_id = u.user_id
AND ".TABLE_PREFIX."medals.medal_type = m.medal_type
)
TABLE_PREFIX is what my script uses to define the database table prefix.
In your sub-query
LEFT JOIN ".TABLE_PREFIX."medals
I think that should be
LEFT JOIN ".TABLE_PREFIX."users_medals
In the subquery you have two medals tables without aliases. I think the FROM ".TABLE_PREFIX."medals should be FROM ".TABLE_PREFIX."users_medals:
SELECT m.*, u.*
FROM ".TABLE_PREFIX."users_medals u
LEFT JOIN ".TABLE_PREFIX."medals m ON u.medal_id = m.medal_id
WHERE u.user_id IN (".$post['uid'].")
AND m.medal_level = (
SELECT MAX(".TABLE_PREFIX."medals.medal_level) FROM ".TABLE_PREFIX."users_medals
LEFT JOIN ".TABLE_PREFIX."medals ON ".TABLE_PREFIX."users_medals.medal_id = ".TABLE_PREFIX."medals.medal_id
WHERE ".TABLE_PREFIX."users_medals.user_id = u.user_id
AND ".TABLE_PREFIX."medals.medal_type = m.medal_type
)