SQL选择具有类似标记的帖子

时间:2017-02-09 13:12:00

标签: php mysql sql database mariadb

在我的MariaDB中,我有一个名为

的表

"帖子"与

id, title, username_id, text, image_url, url

一个名为"标签"与

id, tag

和一个名为post_tags的

id, post_id, tag_id

我想要完成的事情是从"帖子"获得3个帖子。与当前在页面上显示的帖子具有最多共同标签的表格。

我被困在这里不知道从哪里开始。

修改

Posts

id | username_id |   title   |    text     |       image_url      |           url

 1        1         example    example_text  localhost/image.jpg     localhost/first-post
 2        1         example1   example_text  localhost/image1.jpg    localhost/second-post
 3        1         example2   example_text  localhost/image2.jpg    localhost/third-post
 4        1         example4   example_text  localhost/image4.jpg    localhost/fourth-post
...      ...          ...          ...                ...                     ...
...      ...          ...          ...                ...                     ...


Tags

id | tag

 1   herbs
 2   flower
 3   rose

Post_tags

id | post_id | tag_id

 1      1        1
 2      1        2
 3      1        3
 4      2        1
 5      3        1
 6      3        2
 7      4        1
 8      4        2
 9      4        3        

我想返回一个数组posts.titleposts.image_url选择与当前帖子共有post_tags.tag_id最多的帖子。

如你所见,如果我们发帖子。 1作为选定的帖子,发布n。 4具有与它相同的最多标签,后n.3位于第二位置,后n.2是第三位。

example4 | localhost/image4.jpg
example3 | localhost/image3.jpg
example2 | localhost/image2.jpg

我希望我说得更清楚。谢谢。

3 个答案:

答案 0 :(得分:2)

SELECT p.id, p.title, p.image_url, COUNT(*) as how_many_shared_tags
FROM posts p
JOIN post_tags pt ON pt.post_id = p.id
                 AND pt.tag_id IN(SELECT tag_id FROM post_tags WHERE post_id = 1)
WHERE p.id != 1
GROUP BY p.id, p.title, p.image_url
order by COUNT(*) DESC
LIMIT 3

根据要求,查询说明:

  1. 为了找到与我们的“父”帖子共享大多数标签的前3个帖子,我们首先需要获取“父”具有=>的标签列表SELECT tag_id FROM post_tags WHERE post_id = 1
  2. 然后通过添加条件tag_id IN(LIST_OF_tag_id_FROM_SUB_SELECT_SHOWN_ABOVE)来搜索包含帖子和标记ID的表格,找到至少包含其中一个标记的帖子。
  3. 现在我们知道哪些帖子与“父母”共享至少一个标签,因此我们可以计算它们实际上共有多少个标签并按其排序=> order by COUNT(*) DESC
  4. 因为“父”帖子也“共享”了那些标签,我们不希望他在我们的结果中,我们给出了除“我们的父母”的ID以外的其他条件=> WHERE p.id != 1
  5. 最后我们将结果集限制为3行,因为我们只需要前3个。LIMIT 3
  6. 不需要选择计数,只需指出它的重要性COUNT(*) as how_many_common_tags

答案 1 :(得分:0)

如果它给出你想要的东西,请检查它。然后,您可能需要优化查询。

SELECT
t1.*
FROM posts t1,
(
    SELECT
    post_id
    FROM post_tags t2
    WHERE
    tag_id IN (SELECT tag_id FROM post_tags WHERE post_id = $CURRENT_POST_ID)
    AND NOT post_id = $CURRENT_POST_ID
    GROUP BY post_id
    ORDER BY COUNT(tag_id) DESC
    LIMIT 3
) t2
WHERE
t1.id = t2.post_id

答案 2 :(得分:0)

这样只会获得post_id值:

SELECT  x.post_id
    FROM  
    (
        SELECT  b.post_id
            FROM  Post_tags a
            JOIN  Post_tags b USING(tag_id)
            WHERE  a.post_id = 1234
              AND  b.post_id != a.post_id
    ) x
    GROUP BY  x.post_id
    ORDER BY  COUNT(*) DESC
    LIMIT  3;

Tips关于设计更好的映射表(Post_tags)。这将为您提供该表的最佳索引。

要获得有关3个帖子的更多信息:

SELECT  p.*
    FROM  
    (
        SELECT  x.post_id
            FROM  
            (
                SELECT  b.post_id
                    FROM  Post_tag a
                    JOIN  Post_tag b USING(tag_id)
                    WHERE  a.post_id = 1234
                      AND  b.post_id != a.post_id 
            ) AS x
            GROUP BY  x.post_id
            ORDER BY  COUNT(*) DESC
            LIMIT  3 
    ) AS y
    JOIN  Posts AS p  ON p.id = y.post_id;