我在一个名为RELcomplabel的关系表中,标签与公司之间存在多对多关系(MySQL)。基本上看起来像这样:

CREATE TABLE `RELcomplabel` (
    `IDcomplabel` INT NOT NULL AUTO_INCREMENT ,
    PRIMARY KEY (`IDcomplabel`),
    `Fcomp` INT NOT NULL ,
    `Flabel` INT NOT NULL
 );


现在,我要选择所有至少具有给定标签集的公司(我想要的是Fcomp),例如Flabel = 1 AND Flabel = 2 AND Flabel = 3。如果这样的公司在数据库中,则表RELcomplabel中有三行,所有行都具有相同的Fcomp但不同的Flabel(1、2和3)。该查询还应该(尽可能地好)在标签数量上是动态的,它应该可以用于两个标签,但也可以用于十个给定的标签。

我发现了下面两个或三个给定标签的丑陋解决方案。此解决方案的问题是:


动态生成它的丑陋。
内联接的where条件必须检查Ftypet0是否与t1不同,t0t2不同以及t1t2是否不同。
这些查询会生成集合(1,2,3)的所有可能排列,只是选择其中之一。


两个标签的解决方案:

SELECT s.fcomp FROM
(
    SELECT
        t0.fcomp,
        t0.ftype AS type0,
        t1.ftype AS type1
    FROM
        RELcomplabel AS t0
    INNER JOIN
        RELcomplabel AS t1
        ON t0.fcomp = t1.fcomp
    WHERE
        t0.ftype <> t1.ftype
) AS s
WHERE
    s.type0 = 2
    AND s.type1 = 3;


三个标签的解决方案:

SELECT s.fcomp FROM
(
    SELECT
        t0.fcomp,
        t0.ftype AS type0,
        t1.ftype AS type1,
        t2.ftype AS type2
    FROM
        RELcomplabel AS t0
    INNER JOIN
        RELcomplabel AS t1
        ON t0.fcomp = t1.fcomp
    INNER JOIN
        RELcomplabel AS t2
        ON t0.fcomp = t2.fcomp
    WHERE
        t0.ftype <> t1.ftype
        AND t0.ftype <> t2.ftype
        AND t1.ftype <> t2.ftype
) AS s
WHERE
    s.type0 = 1
    AND s.type1 = 2
    AND s.type2 = 3;


例如,使用以下测试数据:

INSERT INTO `relcomplabel` (`IDcomplabel`,`Fcomp`,`Flabel`) VALUES (1,1,1);
INSERT INTO `relcomplabel` (`IDcomplabel`,`Fcomp`,`Flabel`) VALUES (2,1,2);
INSERT INTO `relcomplabel` (`IDcomplabel`,`Fcomp`,`Flabel`) VALUES (3,1,3);
INSERT INTO `relcomplabel` (`IDcomplabel`,`Fcomp`,`Flabel`) VALUES (4,2,2);
INSERT INTO `relcomplabel` (`IDcomplabel`,`Fcomp`,`Flabel`) VALUES (5,2,3);


我正在寻找一个给出类似结果的查询


搜索所有带有标签1和2的公司:

-------
|Fcomp|
-------
| 1   |
| 2   |
-------

搜索所有带有标签1、2和3的公司:

-------
|Fcomp|
-------
| 1   |
-------



感谢您阅读此书,也感谢您发布此问题的方法所提供的帮助!

最佳答案

sqlfiddle回答您的问题http://sqlfiddle.com/#!2/2711e/4

编辑:
添加了SQL,以防小提琴消失:

SELECT Fcomp
FROM RELcomplabel
WHERE Flabel IN (1, 2, 3)
GROUP BY Fcomp
HAVING COUNT(Flabel) >= 3

10-08 15:53