I have two tables:
conversation_participants
id | conversation_id | user_id
int(11) | int(11) | int(11)
users
id | username | ....
int(11) | varchar(20)| ....
I am trying to select all the users which have a certain string in their username which are not (yet) participants in a particular conversation. Currently I have two SQL queries:
SELECT user_id FROM conversation_participants WHERE conversation_id=?
and
SELECT id, username from users WHERE username LIKE '%%%{$_GET['q']}%%' ORDER BY id DESC LIMIT 10
And remove all the results from the second query which have the same user_id as the ones from the first query. Is there any way to merge these two queries into one ?
Thank you in advance
SELECT id, username from users
WHERE username LIKE '%%%{$_GET['q']}%%'
and username not in
(
SELECT user_id FROM conversation_participants
WHERE conversation_id=users.conversation_id
)
ORDER BY id DESC LIMIT 10
Don't build your sql statements concatenating strings. You should use some sort of utility method to sanitize your input. Your statement is prone to sql injection attacks.
PHP has several functions for this. Look into mysql_real_escape_string
In addition to the above answer I have to add, that you should not use $_GET (etc) parameters directly in your query without checking it for SQL injections.
You can also use JOIN, which might be a bit faster.
SELECT u.id, u.username from users u LEFT JOIN conversation_participants c ON c.user_id = u.id WHERE u.username LIKE '%%%{$_GET['q']}%%' AND c.conversation_id != ? ORDER BY u.id DESC LIMIT 10
In addition to the above answer, you could remove your "id" field in the table conversation_participants and define the 2 fields conversation_id and user_id as primary key.
You can do this with a LEFT JOIN together with IS NULL
SELECT
u.id,
u.username
from
users u
LEFT JOIN
conversation_participants cp
ON (u.id=cp.user_id AND cp.conversation_id=?)
WHERE
username LIKE '%%%{$_GET['q']}%%' AND
cp.user_id IS NULL
ORDER BY id DESC LIMIT 10
I believe this is a more optimal solution than using NOT IN() and a sub-query for performance reasons.