我在查找未明确链接的相关数据库行时遇到问题。假设我们有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。
答案 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