Поиск уникальных строк, которым не удается присоединиться в MySQL?

#php #mysql #sql

#php #mysql #sql

Вопрос:

У меня есть две таблицы, одна называется «ключевые слова»; в этой таблице просто хранятся ключевые слова в виде уникального идентификатора ключевого слова и текста ключевого слова. Другая называется «ключевые ссылки»; в этой таблице хранятся строки, связывающие идентификатор носителя с идентификатором ключевого слова.

Если бы у меня был элемент мультимедиа, и я хотел получить все ключевые слова для этого элемента мультимедиа, я бы использовал следующий код:

    SELECT keywords.*, keylinks.*
     FROM keywords
LEFT JOIN keylinks ON (keylinks.keyword_id = keywords.keyword_id)
    WHERE keylinks.media_id = ?
  

Что, если бы я хотел сделать наоборот?
Вместо получения ключевых слов, соответствующих идентификатору носителя, я хотел бы получить ключевые слова, которые НЕ соответствуют идентификатору носителя. Как бы я это сделал? Я не могу просто использовать WHERE keylinks.media_id != ? , потому что это вернуло бы тысячи строк записей ключевых ссылок, которые не относятся к этому конкретному идентификатору носителя, который на самом деле может совпадать с ключевыми словами.

Комментарии:

1. итак, вам нужен media_id, который не соответствует ключевому слову, учитывая, что у вас есть ключевое слово?

2. Я думаю, вы, ребята, немного сбиты с толку тем, что я пытаюсь спросить… Я не ищу все ключевые слова, для которых нет ключевых ссылок… Я ищу все ключевые слова, для которых нет ключевых ссылок, соответствующих определенному идентификатору носителя.

Ответ №1:

Для этого есть как минимум три способа. ANSI предоставляет EXCEPT , который, похоже, не поддерживается MySQL в настоящее время.

ЛЕВОЕ СОЕДИНЕНИЕ / РАВНО НУЛЮ

Размещение критериев с помощью ВНЕШНЕГО соединения имеет решающее значение — если в предложении WHERE критерии применяются после ОБЪЕДИНЕНИЯ. Если критерий находится в соединении, критерий применяется перед СОЕДИНЕНИЕМ.

    SELECT k.*
     FROM KEYWORDS k
LEFT JOIN KEYLINKS kl ON kl.keyword_id = k.keyword_id 
                     AND.media_id = ?
    WHERE keylinks.media_id IS NULL
  

НЕ СУЩЕСТВУЕТ

 SELECT k.*
  FROM KEYWORDS k
 WHERE NOT EXISTS (SELECT NULL 
                     FROM KEYLINKS kl 
                    WHERE kl.keyword_id = k.keyword_id
                      AND kl.media_id = ?)
  

НЕ В

 SELECT k.*
  FROM KEYWORDS k
 WHERE k.keyword_id NOT IN (SELECT kl.keyword_id
                              FROM KEYLINKS kl
                             WHERE kl.media_id = ?)
  

Какая из них работает лучше всего?

Это зависит от того, могут ли сравниваемые столбцы иметь значение null (значение может быть NULL ) или нет.

Комментарии:

1. Я думаю, вы, ребята, немного сбиты с толку тем, что я пытаюсь спросить… Я не ищу все ключевые слова, для которых нет ключевых ссылок… Я ищу все ключевые слова, для которых нет ключевых ссылок, соответствующих определенному идентификатору носителя.

Ответ №2:

 SELECT K1.keyword_id 
  FROM keywords AS K1
 WHERE 
   NOT EXISTS (SELECT * 
                 FROM keylinks AS K2 
                WHERE K2.keyword_id = K1.keyword_id 
                  AND K2.media_id = %d);
  

Это даст вам все ключевые слова, для которых в базе данных нет ключевых ссылок.

Комментарии:

1. Я думаю, вы, ребята, немного сбиты с толку тем, что я пытаюсь спросить… Я не ищу все ключевые слова, для которых нет ключевых ссылок… Я ищу все ключевые слова, для которых нет ключевых ссылок, соответствующих определенному идентификатору носителя.