【问题标题】:MySQL search for a record having AND NOT having specific tagsMySQL 搜索具有且不具有特定标签的记录
【发布时间】:2016-10-28 14:18:30
【问题描述】:

在一个大型项目中(收集...中已解决的问题)我有一个这样组织的数据(典型的 M:N 关系):

records | record_id, other_info
tag_map | map_id, record_id, tag_id
tags    | tag_id, tag_text, other info

我想添加过滤功能。在过滤器中,用户可以为每个标签选择是否需要、忽略或禁止其存在。

例如我需要找到所有记录

  • 有 tag_id = 1 的标签
  • 并且有 tag_id = 4 的标签
  • 并且没有 tag_id = 3 的标签
  • 任何其他标签都不重要。

【问题讨论】:

  • have tag with tag_id = 1 AND have tag with tag_id = 4 ...显然这是不可能的。你是说OR吗?
  • 有可能 - 想象书籍及其标签:小说、冒险、文档、hasImages、wasFilmed。现在我想获取所有有图像、被拍摄且不是小说的书籍。

标签: mysql tags


【解决方案1】:

如果(record_id,tag_id) 元组在tag_map 表中是唯一的,我们可以使用连接和反连接操作的组合。

例如:

 SELECT r.record_id
   FROM records r

   JOIN tag_map t1 
     ON t1.record_id = r.record_id
    AND t1.tag_id    = 1  

   JOIN tag_map t4
     ON t4.record_id = r.record_id
    AND t4.tag_id    = 4

   LEFT
   JOIN tag_map t3
     ON t3.record_id = r.record_id
    AND t3.tag_id    = 3

  WHERE t3.record_id IS NULL

同样,这是基于tag_map 表中(record_id,tag_id) 的唯一性约束的存在。否则,这有可能返回“重复”行。

还有其他可以返回等效结果的查询模式。例如,我们可以使用NOT EXISTS (correlated subquery) 代替反连接。

【讨论】:

  • 谢谢,这是一个解决方案。
【解决方案2】:

SQL 查询:

SELECT records.record_id, records.otherinfo FROM records, tags, tag_map
WHERE records.record_id = tagmap.record_id AND tags.tag_id = tag_map.tag_id 
AND tags.tag_id = 1 AND tags.tag_id = 4 AND <> 3

【讨论】:

  • 这仍会返回与tag_id3 关联的records。它返回与tag_id 1 或 4 相关联的行。规范是记录应该与 both 1 和 4 相关联,而不是与 3 相关联。(我们有什么原因吗? 仍然使用老式逗号语法进行连接操作?)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-18
  • 2022-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多