如何使用一个必需条件和一个可选条件来连接两个表

Jul*_*ian 4 mysql sql

我有一张media桌子和一张tag_media桌子.该tag_media表是一个包含列id_tag和的关系表id_media.单个媒体文件可以使用多个标签进行标记.就像是:

tag_media:
    id_tag
    id_media

media:
    id_media
    (etc, etc)
Run Code Online (Sandbox Code Playgroud)

我需要一个查询,这将允许我获取所有标记有一组强制标记和一组可选标记的媒体,这样我就可以保证返回的媒体被标记为所有必需的标记,并且至少是可选的标记之一标签.

我怎样才能做到这一点?

Eri*_*ikE 6

此查询将执行您要查找的内容:

SELECT
   M.id_media
FROM
   media M
   INNER JOIN tag_media T ON M.id_media = T.id_media
WHERE T.id_tag IN ('required1', 'required2', ... 'optional1', 'optional2', ...)
GROUP BY M.id_media
HAVING
   Sum(T.id_tag IN ('required1', ... 'requiredn')) = <n>
      -- where n is the required number of tags
   AND Sum(T.id_tag IN ('optional1', ... 'optionaln')) >= 1
Run Code Online (Sandbox Code Playgroud)

我喜欢这样的结构,因为那时信息只列出一次:

SELECT
   M.id_media
FROM
   media M
   INNER JOIN tag_media T ON M.id_media = T.id_media
   INNER JOIN (
      SELECT 'required1' id_tag, 1 required UNION ALL SELECT 'required2', 1 ...
      UNION ALL SELECT 'optional1', 0 UNION ALL SELECT 'optional2', 0
   ) S ON T.id_tag = S.id_tag
GROUP BY M.id_media
HAVING
   Sum(required) = <n> -- where n is the required number of tags
   AND Sum(1 - required) >= 1
Run Code Online (Sandbox Code Playgroud)

如果您可以在MySQL中使用CTE,那么将S派生表转换为CTE(或将其放在临时表中)将允许您<n>从所需的选项的字面数更改为(SELECT Count(*) from S).

注意:从技术上讲,这些查询可以重写为完全针对tag_media表.但是如果你想从媒体表中提取其他信息,那么这就是你可能会这样做的.