我有一个存储名为files
的文件信息的表。 files
表格中的每一行都可以与多个类别和标记相关联。
我创建了一个名为file_relationships
的表,用于存储文件及其类别和标记之间的链接。
基本上我想要做的是根据某些类别和标签过滤我的结果。
例如,我可能想要提取标签号为 12 和 15 的所有文件以及类别编号 1 和 2
但是,假设其中一个文件分配了标签号 12 ,但没有任何类别关系。我仍然希望它被包含在结果中。
我还想要包含未分配任何标签和类别的文件。我在下面的SQLFiddle链接中使用fr.relationship IS NULL
实现了这一点。
我已经创建了一个我一直在玩的MySQL代码的快速模拟。这是非常糟糕的代码,但希望它有助于理解我想要实现的目标。
答案 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