SQL: отношения многие ко многим выбирают там, где несколько критериев - PullRequest
0 голосов
/ 28 марта 2019

с учетом этих таблиц:

id_article | title
1          | super article
2          | another article

id_tag | title
1      | great
2      | awesome

id_relation | id_article | id_tag
1           | 1          | 1
2           | 1          | 2
3           | 2          | 1

Я бы хотел иметь возможность выбрать все статьи, которые "великолепны" И "великолепны" (в конце концов, мне, вероятно, придется реализовать ИЛИ тоже)

И в принципе, если я делаю выборку статей, объединяющую таблицу отношений на id_article: конечно, я не могу соединить два разных значения id_tag. Единственный вывод, который я имел, с конкатенацией идентификаторов для проверки в виде строки, но это кажется таким неубедительным, должно быть более красивое решение.

Да, и если это имеет значение, я использую сервер MySQL.

РЕДАКТИРОВАТЬ: для ByWaleed, типичный выбор SQL, который, безусловно, потерпит неудачу, что я привел в своем первоначальном вопросе:

SELECT
    a.id_article,
    a.title
FROM articles a, relations r
WHERE
    r.id_article =  a.id_article and r.id_tag = 1 and r.id_tag = 2

не будет работать, потому что r.id_tag ​​не может быть 1 и 2 на одной строке. Я сомневаюсь, что в w3schools есть статья на эту тему. Мой поиск в Google не дал никакого результата, возможно, потому что я искал с неправильным ключевым словом.

Ответы [ 3 ]

2 голосов
/ 28 марта 2019

Если вы выполняете все объединения как обычно, а затем объединяете строки в одну группу по статье, то вы можете утверждать, что они должны иметь как минимум два разных тега.

(После фильтрации до great и / или awesome это означает, что они имеют оба значения.)

SELECT
    a.id_article,
    a.title
FROM
    articles a
INNER JOIN
    relations r
        ON r.id_article = a.id_article
INNER JOIN
    tags t
        ON t.id_tag = r.id_tag
WHERE
    t.title IN ('great', 'awesome')
GROUP BY
    a.id_article,
    a.title
HAVING
    COUNT(DISTINCT t.id_tag) = 2

(DISTINCT позволяет избежать возможности, например, для одного товара с 'great' дважды.)

Чтобы сделать OR, просто удалите предложение HAVING.

1 голос
/ 28 марта 2019

Шаг 1. Используйте временную таблицу, чтобы получить все статьи с заголовками.

Шаг 2. Если статья появляется в вашей временной таблице несколько раз, это означает, что она имеет отличные и потрясающие заголовки.

Попытка:

CREATE TEMPORARY TABLE MyTempTable (
    select t1.id_article, t2.title
    from table1 t1
    inner join table3 t3 on t3.id_article = t1.id_article
    inner join table2 t2 on t2.id_tag = t3.id_tag
)

select m.id_article
from MyTempTable m
group by m.id_article
having count(*)>1

Редактировать: это решение предполагает, что есть два возможных тега, отличный и потрясающий. Если хотите, добавьте предложение «where» в запрос на выборку для создания временной таблицы, например where t2.title in ('great','awesome')

1 голос
/ 28 марта 2019

Один из подходов - агрегировать по статьям, а затем утверждать, что в статье есть теги "great" и "awesome":

SELECT
    a.id_article,
    a.title
FROM articles a
INNER JOIN relations r
    ON a.id_article = r.id_article
INNER JOIN tags t
    ON r.id_tag = t.id_tag
WHERE
    t.title IN ('great', 'awesome')
GROUP BY
    a.id_article,
    a.title
HAVING
    MIN(t.title) <> MAX(t.title);

enter image description here

Демо

Логика здесь заключается в том, что мы сначала ограничиваем записи для каждой статьи только теми из двух целевых тегов. Затем мы утверждаем, в предложении HAVING, что оба тега появляются. Здесь я использую трюк MIN / MAX, потому что если min и max различаются, то это означает, что есть два разных тега.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...