Combining and/or statements crashing database - mysql

I have the following mysql select. It gets the list of the users qualified on the event and it also gets some results from the users table.
SELECT event.*,
users.first_name,
users.last_name,
users.login,
users.email,
users.f_phone as userphone,
users.f_phone_code
FROM event,
users
WHERE (users.id=event.h_user and f_code LIKE %NEW%)
OR event.h_user = -1
ORDER BY event.`h_id` DESC
Everything worked perfectly, until I tried to get more results by adding the records with h_user = -1. There is not a lot of them, but I guess my query isn't good enough while the database of users is really big. The added OR statement is crashing database while getting results. I tried to add the brackets in WHERE statement but they arent helping.
Would you mind to help me on this please?

It happens because your implicit join conditions become messed up when u add or in the where clause, thus the query doesn't work as you expect it to. Try using explicit join instead (u can make the query work both ways, but explicit notation is just more readable) and leave all the filtering in the where clause:
from event
join users on users.id = event.h_user
where f_code like '%NEW%' or event.h_user = -1
Which would look like this using the implicit notation (don't use it, it is deprecated):
from event, users
where ( users.id = event.h_user ) and
( f_code like '%NEW%' or event.h_user = -1 )

You could also do this with joins and a UNION:
SELECT event.*,
users.first_name,
users.last_name,
users.login,
users.email,
users.f_phone as userphone,
users.f_phone_code
FROM event
INNER JOIN users ON users.id=event.h_user
WHERE f_code LIKE %NEW%
UNION
SELECT event.*,
users.first_name,
users.last_name,
users.login,
users.email,
users.f_phone as userphone,
users.f_phone_code
FROM event
INNER JOIN users ON users.id=event.h_user
WHERE event.h_user = -1
ORDER BY event.`h_id` DESC

Related

SQL AND and OR operators behave unexpected

I'm making the below query:
SELECT
`user_organisation`.*,
`users`.`full_name`,
`users`.`email`,
`users`.`avatar`
FROM
`user_organisation`
INNER JOIN `users` ON `users`.`id` = `user_organisation`.`user_id`
WHERE
`users`.`full_name` LIKE '%test%' OR `users`.`email` LIKE '%test%' AND `user_organisation`.`organisation_id` = 111
And I get the results containing user_organisation.organisation_id equals 111 and 222. I want to search records with users.full_name or users.email containing value test. This SQL successfully searches users with full name or email containing string test but not only user_organisation.organisation_id=111.
What the reason for that unexpected behaviour? I sure I'm missing something but I can't see...
You need parentheses in your WHERE clause around the two ORed terms:
SELECT uo.*, u.full_name, u.email, u.avatar
FROM user_organisation uo
INNER JOIN users u ON u.id = uo.user_id
WHERE (u.full_name LIKE '%test%' OR u.email LIKE '%test%') AND
uo.organisation_id = 111;
Note also that in my answer I am using table aliases (which are abbreviations for full table names). Also, I removed the unnecessary backticks.

Constantly getting syntax error after subquery alias (happens with different queries)

It's probably something I can't seem to understand with MySQL, but after wasting my day going through StackOverflow's related questions without fixing the issue, I decided to ask about it.
SELECT users.idUser, users.name, categoryName
FROM users
LEFT JOIN (
SELECT `translation` as categoryName
FROM localization,
usercategories
WHERE localization.`string` = usercategories.name
AND usercategories.idUserCategory = users.idUserCategory
)
as Something
WHERE users.idUser != 1
ORDER BY users.name ASC
Whichever query I tried today that would include a subquery, I would get the same syntax error at pretty much the same place: right after the subquery's alias (in this case, Something).
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE users.idUser != 1 ORDER BY users.name ASC LIMIT 0, 30' at line 11
This issue here is that you're missing the ON clause of your join. You need to select a condition to join the two tables together, like this:
SELECT stuff
FROM stuff
LEFT JOIN (other stuff)
ON stuff.something = otherstuff.something. // Add here.
You're JOIN criteria is non-ANSI and does not have an ON clause ... perhaps that is causing it? Try this, a bit more optimized:
SELECT Usr.idUser AS idUser
,Usr.name AS name
,UsrCat.translation AS categoryName
FROM users AS Usr
LEFT OUTER JOIN usercategories AS UsrCat
ON UsrCat.idUserCategory = Usr.idUserCategory
LEFT OUTER JOIN localization AS Lcl
ON Lcl.string = UsrCat.name
WHERE Usr.idUser <> 1
ORDER BY Usr.name ASC
No need for subquery, should be pretty performant.
You could re-organize your query so that it does not need a sub-query. This would also allow you the benefit of adding more columns to the select from any of the tables. Also, it is more correct.
SELECT
users.idUser,
users.name,
localization.`translation` as categoryName
FROM users
LEFT JOIN usercategories ON usercategories.idUserCategory = users.idUserCategory
LEFT JOIN localization ON localization.`string`= usercategories.name
WHERE users.idUser <> 1
ORDER BY users.name ASC

MySQL - Operand should contain 1 column(s)

While working on a system I'm creating, I attempted to use the following query in my project:
SELECT
topics.id,
topics.name,
topics.post_count,
topics.view_count,
COUNT( posts.solved_post ) AS solved_post,
(SELECT users.username AS posted_by,
users.id AS posted_by_id
FROM users
WHERE users.id = posts.posted_by)
FROM topics
LEFT OUTER JOIN posts ON posts.topic_id = topics.id
WHERE topics.cat_id = :cat
GROUP BY topics.id
":cat" is bound by my PHP code as I'm using PDO. 2 is a valid value for ":cat".
That query though gives me an error: "#1241 - Operand should contain 1 column(s)"
What stumps me is that I would think that this query would work no problem. Selecting columns, then selecting two more from another table, and continuing on from there. I just can't figure out what the problem is.
Is there a simple fix to this, or another way to write my query?
Your subquery is selecting two columns, while you are using it to project one column (as part of the outer SELECT clause). You can only select one column from such a query in this context.
Consider joining to the users table instead; this will give you more flexibility when selecting what columns you want from users.
SELECT
topics.id,
topics.name,
topics.post_count,
topics.view_count,
COUNT( posts.solved_post ) AS solved_post,
users.username AS posted_by,
users.id AS posted_by_id
FROM topics
LEFT OUTER JOIN posts ON posts.topic_id = topics.id
LEFT OUTER JOIN users ON users.id = posts.posted_by
WHERE topics.cat_id = :cat
GROUP BY topics.id
In my case, the problem was that I sorrounded my columns selection with parenthesis by mistake:
SELECT (p.column1, p.column2, p.column3) FROM table1 p WHERE p.column1 = 1;
And has to be:
SELECT p.column1, p.column2, p.column3 FROM table1 p WHERE p.column1 = 1;
Sounds silly, but it was causing this error and it took some time to figure it out.
This error can also occur if you accidentally use commas instead of AND in the ON clause of a JOIN:
JOIN joined_table ON (joined_table.column = table.column, joined_table.column2 = table.column2)
^
should be AND, not a comma
This error can also occur if you accidentally use = instead of IN in the WHERE clause:
FOR EXAMPLE:
WHERE product_id = (1,2,3);
COUNT( posts.solved_post ) AS solved_post,
(SELECT users.username AS posted_by,
users.id AS posted_by_id
FROM users
WHERE users.id = posts.posted_by)
Well, you can’t get multiple columns from one subquery like that. Luckily, the second column is already posts.posted_by! So:
SELECT
topics.id,
topics.name,
topics.post_count,
topics.view_count,
posts.posted_by
COUNT( posts.solved_post ) AS solved_post,
(SELECT users.username AS posted_by_username
FROM users
WHERE users.id = posts.posted_by)
...
I got this error while executing a MySQL script in an Intellij console, because of adding brackets in the wrong place:
WRONG:
SELECT user.id
FROM user
WHERE id IN (:ids); # Do not put brackets around list argument
RIGHT:
SELECT user.id
FROM user
WHERE id IN :ids; # No brackets is correct
This error can also occur if you accidentally miss if function name.
for example:
set v_filter_value = 100;
select
f_id,
f_sale_value
from
t_seller
where
f_id = 5
and (v_filter_value <> 0, f_sale_value = v_filter_value, true);
Got this problem when I missed putting if in the if function!
Another place this error can happen in is assigning a value that has a comma outside of a string. For example:
SET totalvalue = (IFNULL(i.subtotal,0) + IFNULL(i.tax,0),0)
(SELECT users.username AS posted_by,
users.id AS posted_by_id
FROM users
WHERE users.id = posts.posted_by)
Here you using sub-query but this sub-query must return only one column.
Separate it otherwise it will shows error.
I also have the same issue in making a company database.
this is the code
SELECT FNAME,DNO FROM EMP
WHERE SALARY IN (SELECT MAX(SALARY), DNO
FROM EMP GROUP BY DNO);

MySQL: Missing results

A simple MySQL query is returning a result set that is missing results.
SELECT users.uid, users.firstname, users.lastname, jobs_apps.read_app, jobs_apps.datetime
FROM jobs_apps
JOIN users ON users.uid = jobs_apps.uid
WHERE jobs_apps.job_id = '90'
This returns a 29 rows. If I run the following:
SELECT * FROM jobs_apps WHERE job_id = '90'
I get 31 rows.
The 2 missing results have a value of 0 in the 'read_app' instead of 1.
What could be causing this?
P.S.: I tried running the original query and changing the SELECT clause to simply "SELECT * " and I still only get 29 out of the 31 rows back.
Try an OUTER JOIN in your query
ie;
SELECT users.uid, users.firstname, users.lastname, jobs_apps.read_app, jobs_apps.datetime
FROM jobs_apps
RIGHT OUTER JOIN users ON users.uid = jobs_apps.uid
WHERE jobs_apps.job_id = '90'
Hope this helps :-)

Query Optimization CASE vs UNION

This query returns records of user's friend from friendlist table and then get records of each user from user table.
OPTION # 1
SELECT
f.status,
f.user_to_id,
f.user_from_id,
u.user_id,
u.registration_date,
u.nickname,
u.email
FROM ti_friend_list AS f
LEFT JOIN ti_user u
ON u.user_id = (CASE f.user_from_id
WHEN 7 THEN f.user_to_id
ELSE f.user_from_id END)
WHERE (f.user_from_id = 7
OR f.user_to_id = 7)
OPTION # 2
SELECT
f.status,
f.user_to_id,
f.user_from_id,
u.user_id,
u.registration_date,
u.nickname,
u.email
FROM ti_friend_list AS f
LEFT JOIN ti_user u
ON u.user_id = f.user_to_id
WHERE f.user_from_id = 7
UNION ALL
SELECT
f.status,
f.user_to_id,
f.user_from_id,
u.user_id,
u.registration_date,
u.nickname,
u.email
FROM ti_friend_list AS f
LEFT JOIN ti_user u
ON u.user_id = f.user_from_id
WHERE f.user_to_id = 7
Which One is more optimal solution. Basically a comparison between CASE and UNION
I think like Brian :
I think it is more difficult for the engine to optimize a UNION because you can unifiate very different things !
The problem with UNION is that you must repeat the SELECT part of the query and don't make mistakes
The engine will perform the first part of the union, then the second part and then combine. I think some of the steps will be done twice.
You can try the "explain" command on your queries to see the plan the engine is using.
Run them both and see if there's a time difference!
That aside, I would suggest use of the CASE approach is a clearer one in terms of the intention and ease of extension in the future, and I would use that unless you find clear evidence it's not performing. Off the top of my head I think it would be faster though.