#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
) или нет.
- Если значения не обнуляются,
LEFT JOIN / IS NULL
это самое быстрое средство только в MySQL. - В противном случае, если столбцы обнуляются —
NOT EXISTS
/NOT IN
являются наиболее эффективными.
Комментарии:
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. Я думаю, вы, ребята, немного сбиты с толку тем, что я пытаюсь спросить… Я не ищу все ключевые слова, для которых нет ключевых ссылок… Я ищу все ключевые слова, для которых нет ключевых ссылок, соответствующих определенному идентификатору носителя.