在列表中查找列表

时间:2015-08-21 08:00:43

标签: php mysql

我在查找未明确链接的相关数据库行时遇到问题。假设我们有5张桌子。

Products
Id | name

Product_tags
Id | product_id | tag_id

Tags
Id | name

Blog 
Id | name

Blog_tags
Id | blog_id | tag_ids

所以我所做的就是抓住一个产品,通过Product_tags表抓住这个产品的标签。说我得到这样的东西。

Product 101
Tags 123,124,125,126

现在我有了这个产品页面。问题是,现在我想找到一个博客,如果它适合这个产品,但它不需要拥有产品所有的标签,产品只需拥有所有博客。因此,如果博客有标签124和126,则需要匹配。目前,我将博客中的所有标签保存在一行中(逗号分隔),但如果需要,可以将其更改为每行保存1个标签。如果它被颠倒了我可以做到,但我需要检查不同表格中的部分列表。

Product 101
Tags 123,124,125,126

Should find
Blog 201
Tags 124,126

But not 
Blog 202
Tags 120,124

我尝试了几种方法,但是我无法找到一种方法来完成这项工作,我最接近的尝试是像这样的反向。

select * from Blog_tags where "'".implode(",",$tagIds)."'" LIKE concat("%", tag_ids, "%")

这种方式有效但不适用于产品有1,2,3且博客只有1,3。

1 个答案:

答案 0 :(得分:1)

这是未经测试的,仅来自内存,因此请随意发表评论并告诉我它是否无效。

首先,规范化您的标记列表,不要使用逗号分隔的字符串。你说这可能会改变,所以我打算假设每个标签有一行,列名是tag_id

让我们首先找到包含产品101的一些标签的博客。

SELECT *
FROM Blog
JOIN Blog_tags ON Blog.Id = Blog_tags.blog_id
WHERE tag_id IN (123,124,125,126)
GROUP BY Blog.Id

现在,此查询还将包含标记不在此列表中的博客。所以我们需要删除它们。我觉得这样的事情可行:

SELECT *
FROM (
  SELECT Blog.id as blogId
  FROM Blog
  JOIN Blog_tags ON Blog.Id = Blog_tags.blog_id
  WHERE tag_id IN (123,124,125,126)
  GROUP BY Blog.Id
) as Blog_filtered
LEFT JOIN Blog_tags ON Blog_filtered.blogId = Blog_tags.blog_id AND Blog_tags.tag_id NOT IN (123,124,125,126)
WHERE Blog_tags.id IS NULL
GROUP BY Blog_filtered.blogId