首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >构造用于检索标记项的SQL查询

构造用于检索标记项的SQL查询
EN

Stack Overflow用户
提问于 2013-12-16 21:26:23
回答 1查看 92关注 0票数 0

在下面的示例中,我有三个MySQL (InnoDB)表,其中包含有关饮料及其特性的信息。

  1. 第一个表:“饮料”包含许多不同的饮料。
  2. 下一个表是“标签”,它包含了饮料可以拥有的特性。
  3. 饮料可以有多个标签,在表中定义为“标记”。

表:饮料

代码语言:javascript
运行
复制
+------------------------+
|INT id | VARCHAR name   |
+------------------------+
|  1    |  coca-cola     |
+------------------------+
|  2    |  water         |
+------------------------+
|  3    |  mineral-water |
+------------------------+

表:标记

代码语言:javascript
运行
复制
+-------------------------+
|INT id | VARCHAR tagName |
+-------------------------+
|  1    |  clear          |
+-------------------------+
|  2    |  carbonated     |
+-------------------------+
|  3    |  flavoured      |
+-------------------------+

表:标记的

代码语言:javascript
运行
复制
+------------------------------------+
|INT id | INT beverageId | INT tagId |
+------------------------------------+
|  1    |  1             |  2        | (coca-cola is carbonated)
+------------------------------------+
|  2    |  1             |  3        | (coca-cola is flavoured)
+------------------------------------+
|  3    |  2             |  1        | (water is clear)
+------------------------------------+
|  4    |  3             |  1        | (mineral-water is clear)
+------------------------------------+
|  5    |  3             |  2        | (mineral-water is carbonated)
+------------------------------------+

The fields "beverageId" and "tagId" are foreign keys to the table "beverages".

我想要构建一个查询,允许我提供任意数量的标签,结果将是所有的饮料id都有这些标签。查询将包含任意数量的标记。

  • 如果我提供标签id "2“(碳酸)和标签id "3”(调味品),我会得到饮料id "1“(可口可乐)。
  • 如果我提供标识id "1“(清澈),我会得到饮料id id "2”(水)和id "3“(矿泉水)。
  • 如果我提供标签"2“(碳酸),我会得到饮料id "1”(可口可乐)和饮料id "3“(矿泉水)。

所以问题是;

  1. 为此,表的设计是否合适?
  2. 如何有效地构造这个SQL查询?

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-12-16 21:33:38

THe下面的结构提供了一些关于您可以做什么的指导。下面是将标记is作为独立变量提供的一种方法:

代码语言:javascript
运行
复制
select beverageid
from tagged t
group by beverageid
having sum(tagid = TAGID1) > 0 and
       sum(tagid = TAGID2) > 0 and
       . . . ;

这样的查询很难生成,因为having子句中的子句数量是不同的。

下面是另一种方法,它假设标记位于逗号分隔列表中:

代码语言:javascript
运行
复制
select beverageid
from tagged t
where find_in_set(tagid, TAGLIST) > 0
group by beverageid
having count(distinct tagid) = 
            (length(TAGLIST) - length(replace(TAGLIST, ',', '')) + 1;

这里唯一的混乱之处是计算标签的数量。

如果您正在动态地构造查询,那么当tagid上有一个索引时,下面的结果应该是最好的

代码语言:javascript
运行
复制
select beverageid
from tagged t
where tagid in (TAGLIST)
group by beverageid
having count(distinct tagid) = LENGTH OF TAGLIST;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20621231

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档