Sql 如何查找具有完全包含的标记子集的行
我试图找到一个查询,该查询将返回包含另一种类型的对象(就其标记而言)的对象记录 澄清一下:我有三种类型的对象:数据、项和标记。数据和项目都可以有零个或多个标记。我试图构造一个查询,给定“数据”记录的ID,该查询将返回标记完全包含在“数据”记录中的所有项目记录 因此,给定一个标记为[foo,bar,baz]的数据项,查询将生成一个标记为[foo]或[foo,baz]或[foo,bar,baz]的数据项,但不是标记为[foo,bar,baz,qux]太多的数据项,也不是数据记录中标记为[foo,blah]的数据项Sql 如何查找具有完全包含的标记子集的行,sql,join,Sql,Join,我试图找到一个查询,该查询将返回包含另一种类型的对象(就其标记而言)的对象记录 澄清一下:我有三种类型的对象:数据、项和标记。数据和项目都可以有零个或多个标记。我试图构造一个查询,给定“数据”记录的ID,该查询将返回标记完全包含在“数据”记录中的所有项目记录 因此,给定一个标记为[foo,bar,baz]的数据项,查询将生成一个标记为[foo]或[foo,baz]或[foo,bar,baz]的数据项,但不是标记为[foo,bar,baz,qux]太多的数据项,也不是数据记录中标记为[foo,bl
SELECT i.name
FROM items i
JOIN item_tags it ON it.item_id = i.id
LEFT JOIN data_tags dt ON dt.tag_id = it.tag_id
LEFT JOIN data d ON d.id = dt.data_id AND d.id = 1
GROUP BY i.name
HAVING COUNT(it.tag_id) = COUNT(dt.tag_id)
我很难理解这样一个查询所需的连接
这些表是带有联接表数据\标记的数据、带有联接表项目\标记的项目和标记。我想我需要看看类似于以下伪代码的东西:
选择不同的项目\标记。项目\标识
从数据\u标记交叉连接项目\u标记
其中,item_tags.tag_id=data_tags.tag_id
和data_tags.data_id=?
。。。但我认为这将返回所有与数据中的标记有任何重叠的项,我只希望数据记录中有所有标记的项
SELECT i.name
FROM items i
JOIN item_tags it ON it.item_id = i.id
LEFT JOIN data_tags dt ON dt.tag_id = it.tag_id
LEFT JOIN data d ON d.id = dt.data_id AND d.id = 1
GROUP BY i.name
HAVING COUNT(it.tag_id) = COUNT(dt.tag_id)
假设我有一个数据记录:
在数据_标记中使用标记:
为了简洁起见,两个项目未显示项目标签:
+----+--------+
| id | name |
+----+--------+
| 1 | Item A | // Tags: Foo, Bar
| 2 | Item B | // Tags: Foo, Quux
+----+--------+
查询应该返回项目A,而不是项目B。这似乎是一个相当简单的问题,但我无法理解它。有什么帮助吗
以下是DDL语句:
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `data` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `data_tags` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`data_id` int(11) NOT NULL,
`tag_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `data_id` (`data_id`),
KEY `tag_id` (`tag_id`),
CONSTRAINT `data_tags_ibfk_1` FOREIGN KEY (`data_id`) REFERENCES `data` (`id`),
CONSTRAINT `data_tags_ibfk_2` FOREIGN KEY (`tag_id`) REFERENCES `tag` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `item` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `item_tags` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`item_id` int(11) NOT NULL,
`tag_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `item_id` (`item_id`),
KEY `tag_id` (`tag_id`),
CONSTRAINT `item_tags_ibfk_1` FOREIGN KEY (`item_id`) REFERENCES `item` (`id`),
CONSTRAINT `item_tags_ibfk_2` FOREIGN KEY (`tag_id`) REFERENCES `tag` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `tag` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
您可以通过计算每个项目中的标记并将其与数据记录中匹配标记的数量进行比较来获得所需的结果。只要它们相同,该项就具有数据记录标记的子集
SELECT i.name
FROM items i
JOIN item_tags it ON it.item_id = i.id
LEFT JOIN data_tags dt ON dt.tag_id = it.tag_id
LEFT JOIN data d ON d.id = dt.data_id AND d.id = 1
GROUP BY i.name
HAVING COUNT(it.tag_id) = COUNT(dt.tag_id)
我创建了一个带有几个额外项目的演示:
name tags
Item A Foo,Bar
Item B Foo,Quux
Item C Foo,Bar,Baz
Item D Foo,Bar,Baz,Quux
上述查询的输出为:
name
Item A
Item C
样本数据最好作为+。请将您的问题包括在内,您当前的尝试和您想要的结果。有关更多详细信息,请尝试选择不同的item_tags.item_id FROM data_tags INNER join item_tags On item_tags.tag_id=data_tags.tag_id WHERE data_tags.data_id=?Zohar,谢谢你,并对新手犯的错误表示歉意-我已将DDL声明附在我的原始问题下面。Nick,非常感谢!就是这样。我有一种预感,分组,然后匹配计数就可以了,但我不知道如何做到这一点;我从另一个方向接近它,在数据标签上做交叉连接;我没有想到从item标签开始,但这就是诀窍。@user8092065有时它只是需要一个新的思维来看待这个问题。我很高兴能帮上忙。