我正在使用标记系统,在该标记系统中查询数组(标记),并选择Tag列中具有相同标记的所有行。
问题是我使用了IN条件,这是一种OR函数,它选择了所有具有相同标记的行,而不是缩小它们。例如。
不要使用像“太阳”这样的标签缩小图像范围。和' landscape'它会选择带有这些标签的所有图像。
我正在寻找的是IN()的AND版本或可以使用数组的替代品。
这只是一个例子。实际上,用户可以根据需要添加任意数量的标签
+----+---------+---------+
| ID | ImageID | Tag |
+----+---------+---------+
| 1 | 2 | sun |
+----+---------+---------+
| 2 | 12 |landscape|
+----+---------+---------+
| 3 | 15 | field |
+----+---------+---------+
| 4 | 15 |landscape|
+----+---------+---------+
我的代码
$tag = $_POST['tag'];
$tag = preg_split("#/#", $tag);
$tag = implode("', '", $tag);
$query = "SELECT * FROM ComicStripTags WHERE `Tag` IN ('$tag')";
$result = mysqli_query($link, $query);
while ($row = mysqli_fetch_array($result)){
$ID[] = $row['ImageID'];
}
由于
P.S。我不是在SQL工作,我在PHP工作
答案 0 :(得分:0)
您可以使用内部联接来执行此操作:
select * from TAGS a
inner join TAGS b
on a.ImageID = b.ImageID
where a.tag = 'field'
and b.tag = 'landscape'
根据您的PHP代码:
$joins = [];
$conditions = [];
foreach (preg_split("#/#", $_POST['tag']) as $index => $tag) {
$alias = "ComicStripTags_$index";
$joins[] = "ComicStripTags AS $alias" . ($index > 0 ? " ON ComicStripTags_0.ImageID = $alias.ImageID" : '');
$conditions[] = "$alias.Tag = '$tag'";
}
$query = sprintf("SELECT * FROM %s WHERE %s", implode(' INNER JOIN ', $joins), implode(' AND ', $conditions));
答案 1 :(得分:0)
假设每个ImageID只能包含一个标记,您可以按ImageID进行分组,只选择标记数等于输入数组大小的行。
SELECT ImageID FROM ComicStripTags
WHERE Tag IN ('landscape', 'field')
GROUP BY ImageID HAVING COUNT(Tag) = 2;
答案 2 :(得分:0)
或者你可以做一些支持部分标签匹配的排名:
SELECT
ImageID,
group_concat(Tag) as 'matched_tags',
count(*) as 'tag_matches'
FROM TAGS
WHERE Tag IN ( [list_of_tags] )
GROUP BY ImageID
HAVING tag_matches >= [minimum_number_of_tags]
ORDER BY tag_matches DESC