我正在尝试使用标签构建搜索函数,
我在 MySQL 中的数据结构
parts parts_to_tags tags
---------------------- ---- ------------------- -----------------
| part_id | part_name | |id|part_id|tag_id| |tag_id|tag_name|
| 1 | 20lb Sledge | | 1| 1| 1| | 1|Hammer |
| 2 | Framing Hammer| | 2| 1| 2| | 2|Sledge |
| | | | 3| 2| 1|
我有一个由用户在数组中提供的标签列表,我想将其与这些表进行比较以返回所有结果,因此如果用户要求锤子,则应返回两个工具,但如果他们要求两者或只是雪橇,则应返回 20 磅的雪橇。我不想使用 SQL"IN",因为我想将其用作向下钻取,不是如果存在任何标签,而是结果必须存在所有标签。
我的代码:
$keywords = $_POST['tags'];
// Returns: Array ( [0] => Sledge [1] => Hammer )
$getInventory = $conn -> prepare("SELECT * FROM
parts
LEFT JOIN parts_to_tags ON parts.part_id = parts_to_tags.part_id
LEFT JOIN tags ON parts_to_tags.tag_id = tags.tag_id
");
$getInventory -> execute();
$partArray = $getInventory -> fetchAll();
$matched = !array_diff($keywords, $partArray);
print_r($matched);
但是,$partArray似乎是一个深度数组,所以我无法使用array_diff。有没有人有不同的方法可以解决这个问题?我尝试使用几种不同的提取类型,但我不断在array_diff上收到数组到字符串的转换错误。
谢谢
查询中没有 WHERE
子句;它将返回整个表,这不是你需要的。此外,即使您添加了 WHERE
子句,LEFT JOIN
仍将返回您需要的更多行。
问题的一个可能解决方案可能是:
SELECT p.part_id, p.part_name, GROUP_CONCAT(t.tag_name ORDER BY t.tag_name SEPARATOR '|') AS tags
FROM parts p
INNER JOIN parts_to_tags pt ON p.part_id = pt.part_id
INNER JOIN tags t ON pt.tag_id = t.tag_id
WHERE t.tag_name IN ('Hammer', 'Sledge')
GROUP BY p.part_id
它选择至少具有一个标签的部件,以及与每个部件关联的标签列表,按升序排序并按"|"分隔。
当然,IN ()
条件下的标签名称列表会在 PHP 代码中从 $keywords
生成。
运行查询后PHP
代码:
// Sort the keywords ascending
sort($keywords);
// Concatenate them, use '|' as separator
$allTags = implode('|', $keywords);
// Get the result set
$parts = array();
foreach ($getInventory -> fetchAll() as $row) {
// Keep only the parts that have all the tags
if ($row['tags'] == $allTags) {
$parts[] = $row;
}
}
UPDATE:查询的简化版本,仅返回具有所有指定标记的部分(不需要额外的 PHP 处理):
SELECT p.part_id, p.part_name, COUNT(t.tag_name) AS nbTags
FROM parts p
INNER JOIN parts_to_tags pt ON p.part_id = pt.part_id
INNER JOIN tags t ON pt.tag_id = t.tag_id
WHERE t.tag_name IN ('Hammer', 'Sledge') # <----------------+
GROUP BY p.part_id # |
HAVING nbTags = 2 # The number of strings in this list ---+
如果我理解正确,您可以按如下方式解决。多维数组差异
function arrayRecursiveDiff($aArray1, $aArray2) {
$aReturn = array();
foreach ($aArray1 as $mKey => $mValue) {
if (array_key_exists($mKey, $aArray2)) {
if (is_array($mValue)) {
$aRecursiveDiff = arrayRecursiveDiff($mValue, $aArray2[$mKey]);
if (count($aRecursiveDiff)) { $aReturn[$mKey] = $aRecursiveDiff; }
} else {
if ($mValue != $aArray2[$mKey]) {
$aReturn[$mKey] = $mValue;
}
}
} else {
$aReturn[$mKey] = $mValue;
}
}
return $aReturn;
}
$arr1 = arrayRecursiveDiff($big_array,$small_array);