簡體   English   中英

SQL 選擇具有相似標簽的帖子

[英]SQL select posts that have similar tags

在我的 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的帖子。

如您所見,如果我們使用 post n。 1 作為選定的帖子,發布 n。 4 與它的共同標簽最多,帖子 n.3 位於第二位,帖子 n.2 位於第三位。

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

我希望我說得更清楚。 謝謝你。

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不是必須的,只是指出它算什么COUNT(*) as how_many_common_tags

如果它提供您想要的東西,請檢查它。 那么你可能需要優化查詢。

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

這將為您提供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;

設計更好的映射表 (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;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM