Reputation: 105
I have two tables:
$email = a@a
SELECT * FROM users WHERE email<>'$email' AND channel <> '( SELECT * FROM inscricoes WHERE email ='$email')' ORDER BY RAND();
How to get this result?
d@d | ddddd
Upvotes: 0
Views: 54
Reputation: 108510
I would use an anti-join pattern
SELECT u.email
, u.channel
FROM users u
-- anti-join, exclude rows with matching channel
LEFT
JOIN inscricoes i
ON i.email = 'a@a'
AND i.channel = u.channel
WHERE i.email IS NULL
AND u.email <> 'a@a'
ORDER BY u.channel
That says, get all rows from users
(except for the row for user = 'a@a')
And along with those rows, get any matching rows from inscricoes
.
The twist is the condition in the WHERE
clause.
We are guaranteed that any rows that had a match will have a non-NULL value for i.channel
(since a NULL value would not satisfy the equality condition in the ON clause). So if we exclude rows that have a non-NULL value in i.channel
, we are left with rows that didn't have a match.
An equivalent result can be obtained using a NOT EXISTS (correlated subquery)
pattern
SELECT u.email
, u.channel
FROM users u
WHERE u.email <> 'a@a'
AND NOT EXISTS
( SELECT 1
FROM inscricoes i
WHERE i.email = 'a@a'
AND i.channel = u.channel
)
ORDER BY u.channel
Upvotes: 3
Reputation: 16841
I'm not sure who taught you the ORDER BY RAND()
trick, but I strongly advise forgetting it forever. Unless you absolutely need the results in a random order, this is just slowing down your queries for no reason.
That said, given the data you provided you can do something like this:
SELECT
users.email as email,
users.channel as channel
FROM
users
LEFT JOIN
inscricoes ON users.channel = inscricoes.channel
WHERE
users.email <> '$email'
AND
inscricoes.email <> '$email'
This will create a temporary table:
+-------------+---------------+------------------+--------------------+
| users.email | users.channel | inscricoes.email | inscricoes.channel |
+-------------+---------------+------------------+--------------------+
| a@a | aaaaa | NULL | NULL |
| b@b | bbbbb | a@a | bbbbb |
| c@c | ccccc | a@a | ccccc |
| d@d | ddddd | NULL | NULL |
+-------------+---------------+------------------+--------------------+
Then it runs the query on this temporary table. However if you have multiple values in the inscricoes
table for a single channel, this could lead to duplicate results. If that's the case, let us know and I'll work on a better query for you.
Based on your comment, I think I have a better idea of what you're trying to accomplish. Give this query a try:
SELECT
distinct(channel)
FROM
users
WHERE
email <> '$email'
AND
channel NOT IN (
SELECT channel FROM inscricoes WHERE email = '$email'
)
This will:
a@a
is subscribed to (the subquery)a@a
's channelUpvotes: 2