mysql - 构建 SQL 查询来检索标记的项目

标签 mysql sql

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

  1. 第一个表:“饮料”包含多种不同的饮料。

  2. 下一个表是“标签”,其中包含饮料可以具有的特征。

  3. 一种饮料可以有多个标签,这些标签在“标签”表中定义。

表格:饮料

+------------------------+
|INT id | VARCHAR name   |
+------------------------+
|  1    |  coca-cola     |
+------------------------+
|  2    |  water         |
+------------------------+
|  3    |  mineral-water |
+------------------------+

表格:标签

+-------------------------+
|INT id | VARCHAR tagName |
+-------------------------+
|  1    |  clear          |
+-------------------------+
|  2    |  carbonated     |
+-------------------------+
|  3    |  flavoured      |
+-------------------------+

表:已标记

+------------------------------------+
|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“2”(水)和 ID“3”(矿泉水)。
  • 如果我提供标签“2”(碳酸),我将返回饮料 ID“1”(可口可乐)和饮料 ID“3”(矿泉水)。

所以问题是;

  1. 为此目的,表格设计是否合适?
  2. 应该如何有效地构建此 SQL 查询?

谢谢

最佳答案

以下结构提供了一些有关您可以做什么的指导。以下是一种将标签 ID 作为单独变量提供的方法:

select beverageid
from tagged t
group by beverageid
having sum(tagid = TAGID1) > 0 and
       sum(tagid = TAGID2) > 0 and
       . . . ;

生成这样的查询可能有点困难,因为 having 子句中的子句数量各不相同。

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

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 上有索引时,以下内容应该执行最佳效果:

select beverageid
from tagged t
where tagid in (TAGLIST)
group by beverageid
having count(distinct tagid) = LENGTH OF TAGLIST;

关于mysql - 构建 SQL 查询来检索标记的项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20621231/

相关文章:

mysql - 集合的交集

php - 如何检查数据库中已存在的值?

c# - 将sql脚本转换成可以在sqlite上运行的格式

mysql 和 unicode 字符

php - HTML 表单更改回显变量而不是数据库?

java - 调用两个数据库服务器的最佳方法

MySQL 5.1.65 |选择在哪里找不到我知道的东西

php - 为什么我无法访问该关联数组中的该值/元素?

sql - 按值对行进行分组和计数,直到它发生变化

mysql - 如何将 UNIX TIME 转换为 SQL 日期时间格式