我使用下面的查询将一个中间表与另外两个表连接起来,生成一个线程列表,其中包含与它们相关联的标记。
SELECT th.thread_id, owner_id, message, TIME
FROM threads th
INNER JOIN tag_thread_xref ttx
ON th.thread_id = ttx.thread_id
INNER JOIN tags t
ON ttx.tag_id = t.tag_id
ORDER BY TIME DESC
LIMIT ?
然后,我可以使用WHERE子句来查找与我正在搜索的特定标记关联的线程。我的问题是,如何获取表“threads”中所有行的列表,这些行与标记名数组中的每个元素关联。例如,如果用户搜索标记“television”和“how-i-met-your-mother”,则只返回包含这两个标记的线程。
我对MySQL没有经验,但似乎我想创建第四个临时表,其中只包含一列;我的标记名列表。然后我想将该表作为第三个内部连接添加到我的查询中,以约束该列表。我在这里做到了:
CREATE TEMPORARY TABLE tmp_tag_list (tag_name VARCHAR(30));
INSERT INTO tmp_tag_list (tag_name) VALUES ('television');
INSERT INTO tmp_tag_list (tag_name) VALUES ('how-i-met-your-mother');
SELECT th.thread_id,owner_id,message,time
FROM threads th
INNER JOIN tag_thread_xref ttx
ON th.thread_id = ttx.thread_id
INNER JOIN tags t
ON ttx.tag_id = t.tag_id
INNER JOIN tmp_tag_list tmp
ON t.tag_name = tmp.tag_name
ORDER BY TIME DESC
LIMIT 10
我希望左边的表是“threads”中所有行的集合,这些行有一个与它们相关联的“tag_id”;所有带标记的线程,右边的表是我要筛选的标记的列表。因此,我希望生成的内部联接表只是具有正确表中列出的标记的线程。
我有两个问题:
这不是我得到的结果。相反,此查询返回列出了任何标记的所有线程,有些行出现两次。
即使我能按预期工作,我也看不到如何使用PHP准备好的语句动态地创建数组所需的INSERT子句;除非有其他方法,否则我必须恢复到PHP以前的、不太安全的MySQL查询方法。
有人能就这两个问题提供意见吗?
最佳答案
也许有更好的方法可以做到这一点,但在我的脑海中,你可以选择它在哪一个标签,按线程id和标签分组,然后从中选择,按线程id分组,其中标签的计数(你按它分组,因此每个标签只有一个结果)至少是两个。类似于:
SELECT th.thread_id, owner_id, message, time FROM
(SELECT th.thread_id,owner_id,message,time,tag_name
FROM threads th
INNER JOIN tag_thread_xref ttx
ON th.thread_id = ttx.thread_id
INNER JOIN tags t
ON ttx.tag_id = t.tag_id
WHERE tag_name IN (<?php echo implode(",",$sanitizedTagsArray); ?>)
GROUP BY th.thread_id, tag_name) AS t
GROUP BY th,thread_id
HAVING count(tag_name) >= <?php echo count($sanitizedTagsArray); ?>
如果要使用PDO:
$questionmarks = str_repeat("?,", count($tags)-1) . "?";
...
WHERE tag_name IN (<?php echo $questionmarks ?>)
...
HAVING count(tag_name) >= <?php echo count($tags); ?>
...
$stmt = $db->prepare($query);
$stmt->execute($tags);
然后你就完全安全了
关于php - 比较MySQL查询结果与数组的结果,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21450485/