SQL:多对多关系选择多个条件

时间:2019-03-28 15:05:20

标签: mysql sql

给出这些表:

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

我希望能够选择所有“很棒”和“很棒”的文章(最终,我可能也必须实现OR)

基本上,如果我对article进行选择,那么连接到id_article的关系表:当然,我不能连接id_tag的两个不同值。我只有将ID串联起来才能测试为字符串,但这似乎很la脚,必须有一个更漂亮的解决方案。

哦,如果重要的话,我使用MySQL服务器。

编辑:对于ByWaleed,典型的sql select肯定会失败,而我在原始问题中引用了它:

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 个答案:

答案 0 :(得分:2)

如果您照常进行所有联接,然后按文章将行汇总到一组,则可以断言它们必须至少具有两个不同的标签。

(已经过滤到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 :(得分:1)

一种方法是按文章进行汇总,然后断言文章同时具有“ 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

Demo

这里的逻辑是,我们首先将每篇文章的记录限制为仅两个目标标签的记录。然后,我们断言在HAVING子句中,同时出现两个 标签。我在这里使用了MIN / MAX技巧,因为如果min和max不同,则意味着存在两个不同的标签。

答案 2 :(得分:1)

步骤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')

相关问题