помощь с запросом по таблице отношений

#mysql #sql

#mysql #sql

Вопрос:

Я пытаюсь избавиться от ржавчины в своих навыках SQL и нуждаюсь в некоторой помощи со следующим запросом. База данных, которую я сейчас использую, — mysql.

Я хочу получить все карточки, которым присвоены КАК ‘tag2’, так и ‘tag4’. На основе содержимого существующей таблицы (как видно из приведенного ниже отрывка) запрос должен возвращать две строки: FlashCard_ID 1 и 2.

Как бы я сформулировал этот запрос? Прошло некоторое время с тех пор, как мне приходилось делать что-то подобное.

 mysql> select * from flashcard;
 -------------- ------------ ---------- 
| FLASHCARD_ID | QUESTION   | ANSWER   |
 -------------- ------------ ---------- 
|            1 | Question 1 | Answer 1 |
|            2 | Question 2 | Answer 2 |
|            3 | Question 3 | Answer 3 |
 -------------- ------------ ---------- 
3 rows in set (0.00 sec)

mysql> select * from tag;
 -------- ------ 
| TAG_ID | NAME |
 -------- ------ 
|      1 | tag1 |
|      2 | tag2 |
|      3 | tag3 |
|      4 | tag4 |
|      5 | tag5 |
 -------- ------ 
5 rows in set (0.00 sec)

mysql> select * from flashcard_tags;
 -------- -------------- 
| TAG_ID | FLASHCARD_ID |
 -------- -------------- 
|      2 |            1 |
|      3 |            1 |
|      4 |            1 |
|      2 |            2 |
|      4 |            2 |
|      5 |            2 |
 -------- -------------- 
6 rows in set (0.00 sec)
  

Ответ №1:

 SELECT  f.*
FROM    (
        SELECT  flashcard_id
        FROM    tags t
        JOIN    flashcard_tags ft
        ON      ft.tag_id = t.tag_id
        WHERE   t.name IN ('tag2', 'tag4')
        GROUP BY
                flashcard_id
        HAVING  COUNT(*) = 2
        ) ft
JOIN    flashcard f
ON      f.flashcard_id = ft.flashcard_id
  

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

1. Спасибо. Это работает. Мне интересно, возможно ли это сделать без предложения Having?

2. Можем ли мы использовать следующий запрос? Пожалуйста, поправьте меня, если я сделал что-то не так.

3. «ВЫБЕРИТЕ flashId ИЗ flashcards_tags, ГДЕ tag_id = 2 И СУЩЕСТВУЕТ (ВЫБЕРИТЕ flashId ИЗ flashcards_tags, ГДЕ tag_id = 4)»

4. @Sandeep: ваш подзапрос не коррелирован.

Ответ №2:

 SELECT f.*
FROM flashcard f
  INNER JOIN flashcard_tags ft1 ON f.FLASHCARD_ID = ft1.FLASHCARD_ID
  INNER JOIN tag t1 ON ft1.TAG_ID = t1.TAG_ID AND t1.NAME = 'tag2'
  INNER JOIN flashcard_tags ft2 ON f.FLASHCARD_ID = ft2.FLASHCARD_ID
  INNER JOIN tag t2 ON ft2.TAG_ID = t2.TAG_ID AND t2.NAME = 'tag4'
  

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

1. спасибо за ваш ответ, но я не могу заставить этот запрос возвращать какие-либо строки

2. @Justin: Это потому, что я сначала неправильно понял, извините. Теперь проблем быть не должно.

Ответ №3:

Вот еще один запрос, который работает. Этот не использует подзапрос, и это то, что я в конечном итоге использовал в своем коде гибернации.

 select  fc.FLASHCARD_ID, 
        fc.QUESTION, 
        fc.ANSWER
from    FLASHCARD fc
            inner join FLASHCARD_TAGS fc_t
                on fc.FLASHCARD_ID=fc_t.FLASHCARD_ID 
            inner join TAG t 
                on fc_t.TAG_ID=t.TAG_ID
where   t.Name in ('tag2', 'tag4')
group by fc.FLASHCARD_ID 
having count(t.TAG_ID)=2