【问题标题】:Select all posts (and associated tags) that are tagged with a search选择所有带有搜索标签的帖子(和相关标签)
【发布时间】:2019-08-14 14:30:05
【问题描述】:

我想选择带有一个或多个搜索词的帖子(及其标签)。

这是我的桌子:

发帖

| ID | community | created             | updated             | title | content |
|----|-----------|---------------------|---------------------|-------|---------|
| 99 | 17        | 2019-08-14 14:20:38 | 2019-08-14 14:20:38 | Lorem | Ipsum   |
| 80 | 16        | 2019-07-27 23:11:07 | 2019-07-27 23:11:07 | Lorem | Ipsum   |
| 79 | 16        | 2019-07-27 23:09:47 | 2019-07-27 23:09:47 | Lorem | Ipsum   |

社区

| ID | title          |
|----|----------------|
| 16 | The Scary Door |
| 17 | Other          |

社区标签类别

| Community | Category |
|-----------|----------|
| 16        | 5        |
| 16        | 18       |
| 16        | 19       |
| 16        | 20       |
| 17        | 6        |

标签类别

| category    | ID |
|-------------|----|
| character   | 5  |
| focus       | 18 |
| warning     | 19 |
| time-period | 20 |
| NULL        | 6  |

标签分类

| category | tag |
|----------|-----|
| 5        | 146 |
| 6        | 131 |
| 6        | 147 |
| 19       | 147 |
| 20       | 148 |

标签

| name          | id  |
|---------------|-----|
| spider        | 146 |
| arachnophobia | 147 |
| Victorian era | 148 |
| NULL          | 131 |

发布标签

| post | tag |
|------|-----|
| 99   | 147 |
| 80   | 146 |
| 80   | 147 |
| 80   | 148 |
| 79   | 131 |

我已经在使用这个查询来获取所有帖子及其相关标签和类别的信息:

SELECT p.id, c.id as 'commid', c.title AS 'community', p.title, p.content, p.author, p.created, p.updated, ct.category, t.name AS 'tag'
FROM Post p, Community c, CommunityTagCategories cc, TagCategory ct, TagCategorised tc, Tag t, PostTags pt
WHERE p.community=c.id AND c.id=cc.community AND cc.category=ct.id AND ct.id=tc.category AND tc.tag=t.id AND t.id=pt.tag AND pt.post=p.id
ORDER BY p.created DESC;

如果我搜索“arachnophobia”之类的标签,我希望将结果缩小如下:(如果我想搜索“arachnophobia”和“蜘蛛”,它应该只显示 80 后的信息)

| ID | commid | community      | title | content | author | created             | updated             | category    | tag           |
|----|--------|----------------|-------|---------|--------|---------------------|---------------------|-------------|---------------|
| 99 | 17     | Other          | Lorem | Lorem   | 7      | 2019-08-14 14:20:38 | 2019-08-14 14:20:38 | NULL        | arachnophobia |
| 80 | 16     | The Scary Door | Lorem | Lorem   | 7      | 2019-07-27 23:11:07 | 2019-07-27 23:11:07 | character   | spider        |
| 80 | 16     | The Scary Door | Lorem | Lorem   | 7      | 2019-07-27 23:11:07 | 2019-07-27 23:11:07 | warning     | arachnophobia |
| 80 | 16     | The Scary Door | Lorem | Lorem   | 7      | 2019-07-27 23:11:07 | 2019-07-27 23:11:07 | time-period | Victorian era |

从搜索类似问题看来,我可能需要使用嵌套的 SELECT 和 INNER JOINS。我试着这样做:

SELECT p2.id, c.id as 'commid', c.title AS 'community', p2.author, p2.created, p2.updated, p2.title, p2.content, tc.category, t.name AS 'tag' 
FROM 
    (SELECT p.id
    FROM Post p, Tag t, PostTags pt
    WHERE p.id=pt.post AND pt.tag=t.id AND t.name ="arachnophobia"
    ) search
INNER JOIN Post p2
ON (search.id = p2.id)
INNER JOIN Community c
ON p2.community=c.id
INNER JOIN CommunityTagCategories cc
ON c.id=cc.community
INNER JOIN TagCategory tc
ON cc.category=tc.id
INNER JOIN TagCategorised ct
ON tc.id=ct.category
INNER JOIN Tag t
ON ct.tag=t.id
INNER JOIN PostTags pt
ON t.id=pt.tag
INNER JOIN Post p3
ON pt.post=p3.id
ORDER BY p2.created DESC;       

它只返回帖子 99 和 80 的结果,但它为我提供了与其相关社区中存在的每个标签和类别的结果,即使这些帖子与这些标签和类别无关。 所以这里它为 80 号帖子返回了一个额外的行,带有来自 79 号帖子的标签,它们都在同一个社区中。

| ID | commid | community      | title | content | author | created             | updated             | category    | tag           |
|----|--------|----------------|-------|---------|--------|---------------------|---------------------|-------------|---------------|
| 99 | 17     | Other          | Lorem | Lorem   | 7      | 2019-08-14 14:20:38 | 2019-08-14 14:20:38 | NULL        | arachnophobia |
| 80 | 16     | The Scary Door | Lorem | Lorem   | 7      | 2019-07-27 23:11:07 | 2019-07-27 23:11:07 | character   | spider        |
| 80 | 16     | The Scary Door | Lorem | Lorem   | 7      | 2019-07-27 23:11:07 | 2019-07-27 23:11:07 | warning     | arachnophobia |
| 80 | 16     | The Scary Door | Lorem | Lorem   | 7      | 2019-07-27 23:11:07 | 2019-07-27 23:11:07 | time-period | Victorian era |
| 80 | 16     | The Scary Door | Lorem | Lorem   | 7      | 2019-07-27 23:11:07 | 2019-07-27 23:11:07 | character   | NULL          |

几天前我问了一个关于显示所有帖子数据的类似问题here,用户 nbk 帮助解决了另一个同样有效的查询,但它对我来说有点太复杂了,不知道如何改变自己。

【问题讨论】:

    标签: mysql


    【解决方案1】:

    为避免重复行,您可以使用 DISTINCT:

    SELECT DISTINCT p2.id
      , c.id as commid
      , c.title AS community
      , p2.author
      , p2.created
      , p2.updated
      , p2.title
      , p2.content
      , tc.category
      , t.name AS tag 
    FROM  (
       SELECT p.id
       FROM Post p
       INNER JOIN PostTags pt ON p.id=pt.post
       INNER JOIN Tag t ON  pt.tag=t.id AND t.name ="arachnophobia"
    ) search
    INNER JOIN Post p2 ON search.id = p2.id
    INNER JOIN Community c ON p2.community=c.id
    INNER JOIN CommunityTagCategories cc ON c.id=cc.community
    INNER JOIN TagCategory tc ON cc.category=tc.id
    INNER JOIN TagCategorised ct ON tc.id=ct.category
    INNER JOIN Tag t ON ct.tag=t.id
    INNER JOIN PostTags pt ON t.id=pt.tag
    INNER JOIN Post p3 ON pt.post=p3.id
    ORDER BY p2.created DESC;     
    

    只是一些建议。

    你不应该在列名周围使用单引号(如果是文字的话)在需要时使用反引号。

    不应使用基于表名逗号分隔的旧隐式连接语法和 where 条件(您的子查询中有)。

    避免在连接条件周围出现不必要的 ()。

    看看你的关系:你应该避免加入你已经通过搜索获得的标签的最后一部分。

    SELECT DISTINCT p2.id
      , c.id as commid
      , c.title AS community
      , p2.author
      , p2.created
      , p2.updated
      , p2.title
      , p2.content
      , tc.category
      , t.name AS tag 
    FROM  (
        SELECT p.id
        FROM Post p
        INNER JOIN Tag t ON p.id=pt.post AND t.name ="arachnophobia"
        INNER JOIN PostTags pt ON pt.tag=t.id 
    ) search
    INNER JOIN Post p2 ON search.id = p2.id
    INNER JOIN Community c ON p2.community=c.id
    INNER JOIN CommunityTagCategories cc ON c.id=cc.community
    INNER JOIN TagCategory tc ON cc.category=tc.id
    INNER JOIN TagCategorised ct ON tc.id=ct.category
    ORDER BY p2.created DESC; 
    

    【讨论】:

    • 谢谢。我不得不在嵌套的 SELECT 查询中交换两个 INNER JOIN 表以使其正常工作。不幸的是,它仍然给我不相关标签的结果。例如。如果社区 16 中的帖子 96 被标记为“猫”,那么它会为带有该标签的帖子 80 返回一行,即使帖子 80 没有被标记。
    • 我听说使用 INNER JOIN 比基本的 SELECT FROM WHERE 查询要好,但是与我现在的查询相比,该查询返回了许多重复的行。
    • 当前对所有帖子的查询给了我 21 个结果,但 INNER JOIN 查询返回 315 个结果(SELECT p.id, c.id as 'commid', c.title AS 'community', p. title, p.content, p.author, p.created, p.updated, ct.category, t.name AS 'tag' FROM Post p INNER JOIN Community c ON p.community=c.id INNER JOIN CommunityTagCategories cc ON c .id=cc.community INNER JOIN TagCategory ct ON cc.category=ct.id INNER JOIN TagCategorised tc ON ct.id=tc.category INNER JOIN Tag t ON tc.tag=t.id INNER JOIN PostTags pt ON t.id =pt.tag INNER JOIN Post p2 ON pt.post=p2.id ORDER BY p.created DESC;)
    • 你的 cmets 对我来说不是很清楚......你的意思是重复行 .. 在你的样本(在你的查询上方)中是重复的行 .. 我没有看到重复的 .. . 最终刚刚更新 .. 您的问题添加了一个简单的示例您的实际结果 .. 您预期的结果(以及您使用的查询)
    • 对不起,我添加了上面的实际结果,这有帮助吗?帖子 79 被标记为 NULL,而帖子 80 显示为具有标记 NULL,即使它没有。因此,它为带有未标记标签的帖子提供了额外的行。 INNER JOIN 查询以及我的嵌套 SELECT 和您的嵌套 SELECT 都给了我这些不相关的结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-08
    相关资源
    最近更新 更多