将MySQL查询的结果与数组进行比较

时间:2014-01-30 07:42:06

标签: php mysql sql inner-join

我正在使用以下查询将一个中间表与另外两个表连接起来,以生成一个包含与之关联的标记的线程列表。

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'中与tag_names数组中的每个元素相关联的所有行的列表。例如,如果用户搜索标签“电视”和“我怎么认识你的母亲”,我想只返回包含这些标签的标签的线程。

我对MySQL缺乏经验,但似乎我想创建一个只包含一列的第四个临时表;我的tag_name列表。然后我想将该表作为第三个INNER JOIN添加到我的查询中以约束列表。我在这做过:

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';所有标记的线程,右表是我想要过滤的标记列表。所以我希望得到的内连接表只是在右表中列出标签的线程。

我有两个问题:

  1. 这不是我得到的结果。相反,此查询返回列出了任何标记的所有线程,并且某些行显示两次。

  2. 即使我确实按预期工作,我也看不出如何使用PHP的预处理语句动态创建我的数组所需的INSERT子句;除非有另一种方法,否则我将不得不回到PHP旧的,不太安全的MySQL查询方法。

  3. 任何人都可以就这两个问题提供意见吗?

1 个答案:

答案 0 :(得分:3)

可能有一种更好的方法可以做到这一点,但是在我的脑海中,您可以选择标记,按thread_id和标记分组,然后从中选择,按thread_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);

然后你就完全安全了