SQL n:n - лучшая практика для запросов в соединительной таблице
Я знаю, что для SQL n:n уже запущено много вопросов. Однако я не мог найти решение для моей проблемы.
Я хотел бы создать проект, похожий на личный тезаурус. В нем пользователь может определить, какое слово относится к другим словам. У меня есть две таблицы:
words:
+----+-----------+
| id | word |
+----+-----------+
| 1 | house |
| 2 | residence |
+----+-----------+
words_2_words (junction table)
+----+-------+-------+
| id | word1 | word2 |
+----+-------+-------+
| 1 | 1 | 2 |
+----+-------+-------+
Найти все синонимы для дома довольно легко:
SELECT * FROM words_2_words WHERE word1 = 1;
Однако, чтобы убедиться, я также нахожу слова, которые перечислены только в столбце "word2", мне на самом деле нужно 2 запроса:
SELECT *, word2 AS synonym FROM words_2_words WHERE word1 = 1;
SELECT *, word1 AS synonym FROM words_2_words WHERE word2 = 1;
Как я могу поместить эти 2 запроса в один запрос для более быстрого результата?
2 ответа
Вы могли бы использовать IN
:
SELECT CASE WHEN Word1 = 1 THEN Word2 ELSE Word1 END AS Word
FROM words_2_words
WHERE 1 IN (Word1, Word2):
Или СОЮЗ:
SELECT Word2 AS Word
FROM words_2_words
WHERE Word1 = 1
UNION [ALL]
SELECT Word1
FROM words_2_words
WHERE Word2 = 1;
Добавить или удалить [ALL]
в зависимости от того, хотите ли вы отличные результаты или нет.
Чтобы вернуть реальное слово, я бы порекомендовал просто присоединиться дважды, тогда вы можете получить оба слова:
SELECT CASE WHEN w2w.Word1 = $id THEN w2.Word ELSE w1.Word END AS Word
FROM words_2_words w2w
INNER JOIN words w1
ON w2w.word1 = w1.id
INNER JOIN words w2
ON w2w.word2 = w2.id
WHERE $id IN (w2w.Word1, w2w.Word2):
Если вы действительно не хотите этого делать, вы можете просто использовать тот же оператор case в соединении:
SELECT w.Word
FROM words_2_words w2w
INNER JOIN words w
ON CASE WHEN w2w.Word1 = $id THEN w2w.Word2 ELSE w2w.Word1 END = w.id
WHERE $id IN (w2w.Word1, w2w.Word2):
Если я правильно понимаю, что вы говорите, вы просто запустите:
select * from words_2_words where word1 = 1 or word2 = 1
Хотя вы объединяете 2 запроса, используя объединение, это не похоже на то, что вам действительно нужно делать.