【问题标题】:Selecting intersection of two queries with a single map table in MySQL在 MySQL 中选择两个查询与单个映射表的交集
【发布时间】:2012-06-15 00:33:41
【问题描述】:

我确信这很容易,但请帮帮我,我不知道为什么我不能返回正确的结果。

相当标准的设置,我有一个 ref_product 表、一个 ref_tagmap 表和一个 ref_tag 表...

CREATE TABLE `ref_product` (
`id` DOUBLE ,
`name` VARCHAR (765),
`familyid` DOUBLE ); 

INSERT INTO `ref_product` (`id`, `name`, `familyid`) VALUES('264','Old Red Fixture 1','4');
INSERT INTO `ref_product` (`id`, `name`, `familyid`) VALUES('30206','Modern Red Fixture 2','405');


CREATE TABLE `ref_tag` (
`TagID` DOUBLE ,
`TagName` VARCHAR (150)); 

INSERT INTO `ref_tag` (`TagID`, `TagName`) VALUES('103','Modern Contemporary');
INSERT INTO `ref_tag` (`TagID`, `TagName`) VALUES('131','Red');

CREATE TABLE `ref_tagmap` (
`MapID` DOUBLE ,
`tagid` DOUBLE ,
`containertype` VARCHAR (45),
`containerid` DOUBLE ); 

INSERT INTO `ref_tagmap` (`MapID`, `tagid`, `containertype`, `containerid`) VALUES('17035','131','PROD','264');
INSERT INTO `ref_tagmap` (`MapID`, `tagid`, `containertype`, `containerid`) VALUES('17747','131','PROD','30206');
INSERT INTO `ref_tagmap` (`MapID`, `tagid`, `containertype`, `containerid`) VALUES('31959','103','PROD','30206');

使用以下方法查询这些表:

SELECT DISTINCT ref_product.familyid,ref_tag.tagid
FROM (ref_tag,ref_product)
JOIN ref_tagmap AS mt2 ON  mt2.containerid=ref_product.id
AND  mt2.containertype='PROD'
AND  mt2.tagid=ref_tag.tagid 
AND ref_tag.tagname='red'

正确返回所有映射到标签“红色”的产品系列。同样:

SELECT DISTINCT ref_product.familyid,ref_tag.tagid
FROM (ref_tag,ref_product)
JOIN ref_tagmap AS mt1 ON mt1.containerid=ref_product.id
AND mt1.containertype='PROD'
AND mt1.tagid=ref_tag.tagid 
AND LCASE(ref_tag.tagname)='modern contemporary'

正确返回映射到标签“现代当代”的产品系列。问题是,我如何返回仅包含两个标签映射到它们的产品系列的列表?

我正在尝试这个,它返回空:

SELECT DISTINCT ref_product.familyid,ref_tag.tagid
FROM (ref_tag,ref_product)
JOIN ref_tagmap AS mt2 ON  mt2.containerid=ref_product.id
AND  mt2.containertype='PROD'
AND  mt2.tagid=ref_tag.tagid 
AND ref_tag.tagname='red'
JOIN ref_tagmap AS mt1 ON mt1.containerid=ref_product.id
AND mt1.containertype='PROD'
AND mt1.tagid=ref_tag.tagid 
AND LCASE(ref_tag.tagname)='modern contemporary'

我不得不假设我在这里遗漏了一些基本的东西......感觉很密集。请帮忙。

谢谢!

【问题讨论】:

    标签: mysql join inner-join intersection intersect


    【解决方案1】:

    执行此操作的典型方法是确保tag 表中不同项目的数量等于您希望隔离的标签数量。
    示例:

    SELECT p.familyid
    FROM   ref_product p
           JOIN ref_tagmap tm ON tm.containerid=p.id
           AND tm.containertype='PROD'
           JOIN ref_tag t ON t.tagid = tm.tagid
           AND t.tagname IN ('red',
                             'modern contemporary')
    GROUP BY p.familyid 
    HAVING count(DISTINCT t.tagid) = 2;
    

    实际操作中:http://sqlfiddle.com/#!2/f377e/7

    【讨论】:

    • 伯尼,感谢您的回复...但我不确定这是否会有所帮助。我试图隔离如何构造这个小子句......这是一个非常大的查询的一部分,有十几个条件(还有几个连接的表,我已经在其他东西上分组了。)所以我'我试图了解是否有一种方法可以严格限制返回的结果只返回那些同时映射了两个标签的结果。还有其他方法可以剥这只猫的皮吗?
    • 我要补充一点,我真的不需要返回tag_id或tag_name,只需要返回所有传递的标签所标记的product.familyid。
    • 不客气。请注意,您可以将此查询用作外部查询中的子查询。要么加入它(有人称之为派生表),要么将其用作相关子查询(在外部查询的 WHERE 子句中)。
    • Bernie,不确定你是否还在关注这个线程,但我刚刚有机会重新审视这个悬而未决的问题,并且正如怀疑的那样,将逻辑重写为子查询将执行时间从毫秒推到超过十分钟(这是我对几乎所有 MySQL 子查询的经验)。尽管我对相关查询和派生表进行了研究,但我无法以任何方式将您的按代码分组,而不是简单的 where in(子查询)...我可以举个例子吗?您认为代码的这些变化是否可以接受?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多