查找带有 tag1 和 tag2 的帖子? (using a join-table) Exists / Having / subqueries...用什么?

Finding posts with tag1 AND tag2? (using a join-table) Exists / Having / subqueries... What to use?

我需要进行查询以根据多个字词进行搜索和过滤。

我有一把带武器的 table 并且都可以有多个标签。 我希望能够为用户创建一个过滤器选项,只显示武器,例如'tag1' 和 'tag2'.

到目前为止:
到目前为止,我一直在使用 GROUP_CONCATHAVING 过滤它们,但这存在性能问题!因为我被迫做 GROUP BY w.id 但我想做 ORDER BY 别的事情。 GROUP BY 与 ORDER BY 不能很好地配合....

我尝试使用 EXISTS (SELECT …) 创建一些东西,以便能够过滤多个值,但是当出现“join-table 时我不确定是否这样做” 在中间……(所以有 2 个左连接)

weapons:
id | name
----------
1  | sword
2  | shield

weapon_tag_links:
tag_id  | weapon_id
-------------------
62      | 1
80      | 1
80      | 2
60      | 2

weapon_tags:
tag_id | tag
--------------
60      | red
62      | blue
80      | old

搜索查询:

SELECT DISTINCT * FROM weapons as w
LEFT JOIN weapon_tag_links AS l ON l.weapon_id = w.id 
INNER JOIN weapon_tags AS t ON l.tag_id = t.tag_id 
WHERE EXISTS (
    ****** Something to go here *******
    WHERE t.tag = ‘blue’
) AND EXISTS (
    ****** Something to go here *******
    WHERE t.tag = ‘old’
)

我只是缺少您在 EXISTS 中需要的 link。但是我不确定如何添加这个…

问题:
假设我想搜索 blueold 的武器记录(在本例中是一把剑)我该怎么做?

我并不是说我必须使用 "EXISTS",但我想要最佳优化的方式来搜索带有由 AND! 连接的某些标签的帖子

试试这个:

SELECT * FROM wp_posts AS p
LEFT JOIN wp_term_relationships AS tr ON p.ID = tr.object_id 
LEFT JOIN wp_terms AS t ON tr.term_taxonomy_id = t.term_id 
WHERE p.id IN 
(
    SELECT p2.id FROM wp_posts AS p2
    LEFT JOIN wp_term_relationships AS tr2 ON p2.ID = tr2.object_id 
    LEFT JOIN wp_terms AS t2 ON tr2.term_taxonomy_id = t2.term_id 
    GROUP BY p2.id
    HAVING FIND_IN_SET('blue', GROUP_CONCAT(t2.term)) AND FIND_IN_SET('old', GROUP_CONCAT(t2.term))
)

转过来。那是从最里面的子查询中的 tag IN ('blue', 'old') 开始的。从中找到 tag_ids。从他们身上,找到weapon_idsHAVING COUNT(*) = 2。最后,在最外层的查询中,获取 weapon.name.

没有EXISTS()。没有LEFT JOINs;我不确定您一开始是否需要 LEFT

您最初的尝试需要使用不同的别名两次加入 tag。我通过使用 INHAVING.

来避免这种情况

更多

是的,这有点棘手...

SELECT
     FROM  
      ( SELECT  weapon_id
            FROM  weapon_tags
            JOIN  weapon_tag_links USING(tag_id)
            WHERE  tag IN ('blue', 'old')
            GROUP BY  weapon_id
            HAVING  COUNT(*) >= 2 
      ) a
    JOIN  weapons w ON w.id = a.weapon_id;

如果你没有规范化标签会更容易。