MySQL:连接的表列没有特定的列值

时间:2013-07-13 11:47:41

标签: mysql

我有一个存储名为files的文件信息的表。 files表格中的每一行都可以与多个类别标记相关联。

我创建了一个名为file_relationships的表,用于存储文件及其类别和标记之间的链接。

基本上我想要做的是根据某些类别和标签过滤我的结果。

例如,我可能想要提取标签号为 12 15 的所有文件以及类别编号 1 2

但是,假设其中一个文件分配了标签号 12 ,但没有任何类别关系。我仍然希望它被包含在结果中。

我还想要包含未分配任何标签和类别的文件。我在下面的SQLFiddle链接中使用fr.relationship IS NULL实现了这一点。

我已经创建了一个我一直在玩的MySQL代码的快速模拟。这是非常糟糕的代码,但希望它有助于理解我想要实现的目标。

http://sqlfiddle.com/#!2/931f2/1

2 个答案:

答案 0 :(得分:1)

我想我有你想要的东西,但让我明白地解释发生了什么。我只是从文件关系表中预先查询(别名PQ)每个文件ID的聚合。这些聚合基本上是1或0的标志,表明它有或没有。

左连接的结果,如果根本没有关系,你想要输入,所以你的IS NULL显然是好的。

现在,您考虑的是没有任何“TAG”或“CAT”条目的文件。这是HasOtherRelation的MAX(IF())进来的地方。通过给定文件ID的所有条目,我关心的是“除了cat或tag之外是否有任何条目”...如果是这样,设置为1类似于“HasTagOrCat”的标志,所以在我的where子句中,我正在寻找具有其他关系= 1且Has标签或Cat标志为零的任何内容。

最后,关于满足您对标记或猫限定符的考虑的要求,但是如果文件具有其他cat或tag条目则不符合您的要求。类似的MAX(IF())用于那些。

select
      f.id,
      f.file_title
   from
      files f
         LEFT JOIN
         ( select 
                 fr.file_id,
                 max( if( fr.relationship IN ('tag','cat'), 1, 0 )) as HasTagOrCat,
                 max( if( fr.relationship NOT IN ('tag','cat'), 1, 0 )) as HasOtherRelation,
                 max( if( fr.relationship = 'tag' AND fr.relationship_id IN('12','15'), 1, 0 )) as HasTags,
                 max( if( fr.relationship = 'cat' AND fr.relationship_id IN('1','2'), 1, 0 )) as HasCats,
                 max( if( fr.relationship = 'tag' AND fr.relationship_id NOT IN('12','15'), 1, 0 )) as HasOtherTags,
                 max( if( fr.relationship = 'cat' AND fr.relationship_id NOT IN('1','2'), 1, 0 )) as HasOtherCats
              from 
                 file_relationships AS fr
              group by
                 fr.file_id ) PQ
         ON f.id = PQ.file_id
   where
         PQ.file_id IS NULL
      OR (    PQ.HasOtherRelation = 1
          AND PQ.HasTagOrCat = 0 )
      OR (    PQ.HasTags + PQ.HasCats > 0
          AND PQ.HasOtherTags + PQ.HasOtherCats = 0 )

因此,在内部预查询结束时,您的结果将具有以下内容

File_ID  HasTagOrCat  HasOtherRelation  HasTags  HasCats  HasOtherTags  HasOtherCats
1        1            0                 1        1        0             0
2        1            0                 1        1        1             1
3        1            0                 1        0        0             0

因此,您的数据在数据样本中没有任何此类非标记/ cat注意事项,也没有在关系表中没有此类文件条目的任何NULL,但是如上所述的其他数据将仅导致文件1和文件1。 3包含在结果集中......

他们每个人都至少有一个标签或猫,你正在寻找一个你不想要的NO OTHER标签/猫。对于条目2,是的,它既有你正在寻找的标签和猫,也有你没有的其他标签/猫,因此被排除在结果之外。

答案 1 :(得分:0)

替换并使用或 --->

fr.relationship ='tag' AND fr.relationship_id IN('12','15')) fr.relationship ='cat'和fr.relationship_id IN('1','2'))

你正在检查fr.relationship ='tag'和fr.relationship ='cat' fr.relationship可以是'cat'或fr.relationship可以'标记'为1记录/行 不能等于两个值

SELECT f.id,
       f.file_title ,fr.relationship
FROM files AS f
LEFT JOIN file_relationships AS fr
  ON f.id = fr.file_id
and /*REPLACEMENT as u want null column also */ (
  fr.relationship IS NULL
  OR (fr.relationship NOT IN ('tag','cat'))
  OR (
    (fr.relationship = 'tag' AND fr.relationship_id IN('12','15'))
    or (fr.relationship = 'cat' AND fr.relationship_id IN('1', '2'))
  )
)
GROUP BY f.id
EDIT---

这就是你想要的    http://sqlfiddle.com/#!2/df016d/4

SELECT f.id,
       f.file_title ,group_concat(fr.relationship)
FROM files AS f
LEFT JOIN file_relationships AS fr
  ON f.id = fr.file_id
and  (
  fr.relationship IS NULL
  OR (fr.relationship NOT IN ('tag','cat'))
  OR (
    (fr.relationship = 'tag' AND fr.relationship_id IN('12','15'))
    or (fr.relationship = 'cat' AND fr.relationship_id IN('1', '2'))
  )
)
GROUP BY f.id