简体   繁体   English

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

[英]Compare Results of MySQL Query against array

I'm using the following query to join an intermediate table with two others, to generate a list of threads which have tags associated with them. 我正在使用以下查询将中间表与另外两个表连接,以生成具有与之关联的标记的线程列表。

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 ?         

I can then use a WHERE clause to find threads which are associated with a particular tag I'm searching for. 然后我可以使用WHERE子句来查找与我正在搜索的特定标记相关联的线程。 My problem though figuring out how to get a list of all rows in table 'threads' which are associated with every element in an array of tag_names. 我的问题虽然弄清楚如何获取表'threads'中与tag_names数组中的每个元素相关联的所有行的列表。 For example, if the user does a search for tags 'television' and 'how-i-met-your-mother', I want to return only threads with contain BOTH of those tags. 例如,如果用户搜索标签'television'和'how-i-met-your-mother',我想只返回包含那些标签的BOTH的线程。

I'm inexperienced with MySQL, but it seems like I want to create a fourth temporary table which contains only one column; 我对MySQL缺乏经验,但似乎我想创建一个只包含一列的第四个临时表; my list of tag_name's. 我的tag_name列表。 I then want to add that table as a third INNER JOIN to my query to constrain the list. 然后我想将该表作为第三个INNER JOIN添加到我的查询中以约束列表。 I've done that here: 我在这做了:

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

I expect the left table to be a collection of all rows from 'threads' which have a 'tag_id' associated with them; 我希望左表是'threads'中所有行的集合,这些行具有与它们相关联的'tag_id'; all tagged threads, and the right table to be a list of the tags I want to filter by. 所有标记的线程,右表是我想要过滤的标记列表。 So I would expect the resulting inner join table to be only threads which have the tags listed in the right table. 所以我希望得到的内连接表只是在右表中列出标签的线程。

I have two problems: 我有两个问题:

  1. This isn't the result I'm getting. 这不是我得到的结果。 Instead, this query returns all threads which have ANY of the tags listed, and some rows appear twice. 相反,此查询返回列出了任何标记的所有线程,并且某些行显示两次。

  2. Even if I do get this to work as expected, I don't see how I can use PHP's prepared statements to dynamically create as many INSERT clauses as are required for my array; 即使我确实按预期工作,我也看不出如何使用PHP的预处理语句动态创建我的数组所需的INSERT子句; I would have to revert back to PHP's old, less secure method of MySQL queries, unless there is another way. 除非有另一种方法,否则我将不得不回到PHP旧的,不太安全的MySQL查询方法。

Can anyone offer input on either of these issues? 任何人都可以就这两个问题提供意见吗?

There is probably a better way to do this, but off the top of my head, you could select where it is either tag, group by thread_id and tag, and then select from that, group by thread_id, where the count of tags (which you grouped by, so will only have one result for each tag) is at least two. 有一种更好的方法可以做到这一点,但是在我的脑海中,您可以选择它是标记,按thread_id和标记分组,然后从中选择,按thread_id分组,其中标记的数量(你分组,所以每个标签只有一个结果)至少是两个。 Something like: 就像是:

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); ?>

If you want to use PDO: 如果要使用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);

And then you're totally safe 然后你就完全安全了

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM