2014-02-18 2 views
1

Я знаю, что уже существует много вопросов для 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

!!! См. СОЮЗ !!! – Strawberry

ответ

1

Вы можете использовать IN:

SELECT CASE WHEN Word1 = 1 THEN Word2 ELSE Word1 END AS Word 
FROM words_2_words 
WHERE 1 IN (Word1, Word2): 

Или UNION:

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): 

Если вы действительно не хотите, чтобы сделать это, вы можете просто использовать то же дело с заявлением в объединении:

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): 
+0

Спасибо, часть IN, похоже, хорошо работает для меня. Какие из ваших двух предложений будут лучше с точки зрения производительности? – mdthh

+1

Я бы предположил, что первый, но не зная, какие индексы у вас есть, и ваше распространение данных, я не мог сказать наверняка. Попробуйте оба и посмотрите, что быстрее с вашими данными. – GarethD

+0

Теперь у меня есть другая проблема: как присоединиться к таблице слов, поэтому я получаю фактическое слово. Это ** не ** работа: 'ВЫБРАТЬ случай, когда word1 = $ идентификатор THEN ELSE word2 word1 END AS ху \t \t ОТ words2words \t \t LEFT JOIN \t \t слова ON ху = words.id \t \t ГДЕ $ id IN (word1, word2) ' – mdthh

1

Если я понимаю, что вы правильно говорите, вы бы просто запустить:

select * from words_2_words where word1 = 1 or word2 = 1 

Хотя объединить 2 запросов с помощью объединения, которое не кажется, что это то, что вам на самом деле нужно сделать.

+0

Спасибо за ваш ответ. Проблема с вашим решением (которое я уже пробовал): у меня нет определенного поля, которое показывает мне отношение двух слов; это слово1 или слово2? (Извините, трудно объяснить. Не знаю всех технических терминов) – mdthh

Смежные вопросы