Как выбрать значение из одной таблицы, в которой две отдельные пары условий выполняются в другой таблице - PullRequest
1 голос
/ 24 октября 2019

Извините, если это плохой вопрос. Я новичок в SQL и не смог найти ответ сам.

У меня есть две таблицы. Первая таблица содержит идентификатор и уникальные слова. Вторая таблица содержит идентификатор, имя-свойства и имя-свойства и может иметь несколько свойств для каждого слова.

слово

+----+------+
| id | word |
+----+------+
|  1 | dog  |
|  2 | tree |
|  3 | dang |
|  4 | frog |
+----+------+

свойство

+----+---------------+----------------+
| id | property_name | property_value |
+----+---------------+----------------+
|  1 | letters       | 3              |
|  1 | first_letter  | d              |
|  2 | letters       | 4              |
|  2 | first_letter  | t              |
|  3 | letters       | 4              |
|  3 | first_letter  | d              |
|  4 | letters       | 4              |
|  4 | first_letter  | f              |
+----+---------------+----------------+

Я хочу выбрать слово, в котором выполняются два набора условий. Ниже приведен псевдокод того, чего я пытаюсь достичь.

SELECT word
WHERE 
1) (property_name = 'letters' and property_value = '3')
2) (property_name = 'first_letter' and property_value = 'd')

Сначала я искал в Google примеры соединения одной таблицы с другой, где для каждого значения в первой таблице может существовать несколько свойств. У меня было много трудностей с описанием того, что я искал, и я не смог ничего найти в Google. Я также искал переполнение стека для похожих вопросов, но вопросы были только смутно похожи, и ответы не работали для меня. Все вместе, это мой третий день подряд, пытающийся найти это решение.

Ниже приведены несколько моих попыток:

Я попытался вложить оператор and.

SELECT w.word
FROM word w
LEFT JOIN property p ON (w.id = p.id)
WHERE ((p.property_name = 'letters' and p.property_value = '3') and
(p.property_name = 'first_letter' and p.property_value = 'd'))
GROUP BY w.word

Я также пробовал несколько левых соединений.

SELECT w.word
FROM word w
LEFT JOIN property p ON (w.id = p.id)
WHERE (p.property_name = 'letters' and p.property_value = '3')
LEFT JOIN property p ON (w.id = p.id)
WHERE (p.property_name = 'first_letter' and p.property_value = 'd')
GROUP BY w.word

Первая попытка, приведенная выше, возвращает объединенную таблицу, в которой выполняется только первое условие. Вторая попытка возвращает синтаксическую ошибку.

Было больше неудачных попыток, но я не включил их для краткости.

Для псевдокода, который я написал выше, мой желаемый результат:

dog

Я простоне знаю, как написать запрос, который делает это.

Ответы [ 2 ]

2 голосов
/ 24 октября 2019

Используя INTERSECT, вы можете написать эффективный, интуитивно понятный запрос, который на самом деле очень похож на тот, который вы написали в первый раз:

SELECT word FROM words
WHERE id IN (
  SELECT id FROM properties WHERE property_name = 'letters' AND property_value = '3'
  INTERSECT
  SELECT id FROM properties WHERE property_name = 'first_letter' AND property_value = 'd'
);
2 голосов
/ 24 октября 2019

во-первых, не используйте left join, если вы хотите получить соответствие property своему word второму, не нужно использовать group by, вы не используете aggregation function.

select w.word
from word w
inner join property p on w.id = p.id and p.property_name = 'letters' and p.property_value = '3'
inner join property p2 on w.id = p2.id  and p2.property_name = 'first_letter' and p2.property_value = 'd'

или вы можете использовать exists ключевое слово

select w.word
from word w
where 
    exists (select 1 from property p where w.id = p.id 
        and p.property_name = 'letters' and p.property_value = '3')
    and
    exists (select 1 from property p where w.id = p.id 
        and p.property_name = 'first_letter' and p.property_value = 'd')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...