Подтвердить что ты не робот

Mysql запрос, чтобы выбрать все, кроме

У меня есть две таблицы mysql.

первый называется "выбранным" и состоит из полей id, user_id и widget_id.

другой называется "виджеты" и включает в себя несколько вещей, включая widget_id.

я создал фильтр, чтобы пользователь мог либо отображать выбранные им виджеты, либо виджеты, которые он/она не выбрал. для тех, которые он выбрал, я использую это:

SELECT * 
  FROM widgets, chosen 
 WHERE chosen.user_id = $user_id 
   AND chosen.widget_id = widgets.widget_id

Однако я не могу понять, как отображать те, которые он/она не выбрал. это не работает (отображает все):

SELECT * 
  FROM widgets, chosen 
 WHERE !(    chosen.user_id = $user_id 
         AND chosen.widget_id = widgets.widget_id)

как это сделать?

4b9b3361

Ответ 1

Использование NOT IN:

SELECT w.*
  FROM WIDGET w
 WHERE w.widget_id NOT IN (SELECT c.widget
                             FROM CHOSEN c
                            WHERE c.user_id = $user_id)

Использование NOT EXISTS:

SELECT w.*
  FROM WIDGET w
 WHERE NOT EXISTS (SELECT NULL
                     FROM CHOSEN c
                    WHERE c.widget_id = w.widget_id 
                      AND c.user_id = $user_id)

LEFT JOIN/IS NULL:

   SELECT w.*
     FROM WIDGET w
LEFT JOIN CHOSEN c ON c.widget_id = w.widget
                  AND c.user_id = $user_id
    WHERE w.widget IS NULL

Производительность:

Если сравниваемые столбцы (widget_id в любой таблице) не могут быть нулевыми, LEFT JOIN/IS NULL лучше всего работает в MySQL. Если столбцы имеют значение NULL (значение может быть NULL), NOT IN или NOT EXISTS работают лучше.

Ответ 2

Логическая логика: (ab)' совпадает с a' + b'

SELECT * 
  FROM widgets, chosen 
 WHERE chosen.user_id <> $user_id 
         OR chosen.widget_id <> widgets.widget_id

Ответ 3

В принципе, вы хотите выбрать все строки из widgets, у которых нет соответствующей строки в chosen для данного $user_id. Вы можете выполнить это с помощью LEFT OUTER JOIN для поиска строк, которые не совпадают в таблице chosen. Что-то вроде этого:

SELECT w.* FROM widgets as w
LEFT OUTER JOIN chosen as c on c.widget_id=w.widget_id AND c.user_id=$user_id
WHERE c.id IS NULL;

BTW: Я рекомендую использовать синтаксис нового синтаксиса по синтаксису объединения таблиц с разделителями-запятыми. Это легче читать и понимать, особенно когда речь идет о внешних объединениях.