Как сравнить два выбора?

0

У меня две таблицы:

Изображение 174551

  $email = a@a
  SELECT * FROM users WHERE email<>'$email' AND channel <> '( SELECT * FROM inscricoes WHERE email ='$email')' ORDER BY RAND();

Как получить этот результат?

d@d    |    ddddd
  • 1
    Почему d@d а не c@c ?
  • 0
    Возможно SELECT * FROM users WHERE email<>'$email' AND channel not in (SELECT channel FROM inscricoes WHERE email ='$email') ORDER BY RAND(); ?
Показать ещё 2 комментария
Теги:

2 ответа

3
Лучший ответ

Я бы использовал шаблон против объединения

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

Это говорит о том, чтобы получить все строки от users (кроме строки для пользователя = 'a @a')

И вместе с этими строками, получите любые соответствующие строки от inscricoes.

Твист - это условие в WHERE.

Мы гарантируем, что любые строки, имеющие совпадение, будут иметь значение, i.channel NULL для i.channel (поскольку значение NULL не удовлетворяет условию равенства в предложении ON). Поэтому, если мы исключаем строки, которые имеют значение, i.channel NULL, в i.channel, мы оставляем строки, которые не имеют соответствия.


Эквивалентный результат может быть получен с использованием шаблона NOT EXISTS (correlated subquery)

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 
  • 0
    +1 для шаблона против присоединения. Это может на самом деле работать быстрее, чем мое решение подзапрос + фильтр, если есть много строк
  • 0
    @stevendesu: по моему опыту, шаблон анти-объединения имеет тенденцию работать быстрее, по крайней мере, с большими наборами и с доступными соответствующими индексами. я бы не исключил, что другие шаблоны запросов будут быстрее в других случаях (например, нет подходящих индексов или необъяснимых предикатов, меньших наборов или наборов с ненормативным распределением данных, статистикой. хорошо иметь множество инструментов в наших инструментальных наборах SQL ,
2

Я не уверен, кто научил вас ORDER BY RAND() трюк, но я настоятельно советую забыть его навсегда. Если вам абсолютно не нужны результаты в случайном порядке, это просто замедляет ваши запросы без причины.

Тем не менее, учитывая предоставленные вами данные, вы можете сделать что-то вроде этого:

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'

Это создаст временную таблицу:

+-------------+---------------+------------------+--------------------+
| 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               |
+-------------+---------------+------------------+--------------------+

Затем он запускает запрос на эту временную таблицу. Однако, если у вас есть несколько значений в таблице inscricoes для одного канала, это может привести к дублированию результатов. Если это случай, сообщите нам, и я буду работать над лучшим запросом для вас.

редактировать

Основываясь на вашем комментарии, я думаю, что у меня есть лучшее представление о том, чего вы пытаетесь достичь. Попробуйте этот запрос:

SELECT
    distinct(channel)
FROM
    users
WHERE
    email <> '$email'
    AND
    channel NOT IN (
        SELECT channel FROM inscricoes WHERE email = '$email'
    )

Это будет:

  1. Получить список каналов, на которые a@a (подзапрос)
  2. Получить список всех каналов, исключая канал a@a
  3. Отфильтровать первый список из второго списка
  4. Возврат всех результатов (игнорирование дубликатов)
  • 0
    абсолютно не нужно случайных, мне нужно показать пользователю только список каналов, на которые он еще не подписан. Если он уже зарегистрировался, ему не нужно показывать ему каналы.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню