【问题标题】:Get all posts from a specific category获取特定类别的所有帖子
【发布时间】:2011-07-03 09:54:22
【问题描述】:

情况

你们中的一些人可能已经从我之前的问题中知道,我目前正在开发一个博客系统。

这一次,我一直在获取来自特定类别的所有帖子及其类别。

数据库

这里是创建三个必需表的 SQL 命令。

发布

create table Post(
    headline varchar(100),
    date datetime,
    content text,
    author int unsigned,
    public tinyint,
    type int,
    ID serial,
    Primary Key (ID),
)ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

author 是创建帖子的用户的 ID,public 确定帖子是否可以被所有人阅读或只是草稿,type 确定它是否是博客帖子 (0)或者别的什么。

类别

create table Kategorie(
    name varchar(30),
    short varchar(200),
    ID serial,
    Primary Key (name)
)ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Post_Kategorie

create table Post_Kategorie(
    post_ID bigint unsigned,
    kategorie_ID bigint unsigned,
    Primary Key (post_ID, kategorie_ID),
    Foreign Key (post_ID) references Post(ID),
    Foreign Key (kategorie_ID) references Kategorie(ID)
)ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

查询

这是我当前的查询,用于获取标记为特定类别的所有帖子,该类别由类别的 ID 确定:

SELECT Post.headline, Post.date, Post.ID,
  CONCAT(
    "[", GROUP_CONCAT('{"name":"',Kategorie.name,'","id":',Kategorie.ID,'}'), "]"
  ) as "categorys"
FROM Post
INNER JOIN Post_Kategorie
  ON Post.ID = Post_Kategorie.post_ID
INNER JOIN Kategorie
  ON Post_Kategorie.kategorie_ID = 2
WHERE Post.public = 1
  AND Post.type = 0
GROUP BY Post.headline, Post.date
ORDER BY Post.date DESC
LIMIT 0, 20

该查询适用于列出所有标记为特定类别的帖子,但categorys-列会混淆,因为每个列出的帖子都有所有可用类别(Kategorie-表中列出的每个类别)。

我确定问题出在INNER JOIN-条件中,但我不知道在哪里。请指出正确的方向。

【问题讨论】:

  • 在发布与前一个问题相关的问题时,重复详细信息一定很乏味。所以我理解你为什么要向我们介绍你之前的问题。但是,您不认为在问题之间跳转以收集获取图片所需的所有信息同样乏味吗?
  • 我也在这个问题中添加了详细信息。

标签: mysql sql select join


【解决方案1】:

我怀疑您的 CONCAT 函数可能存在问题,因为它混合了不同类型的引号。我认为"[""]" 应该分别是'['']'

否则,问题似乎出在其中一个联接上。特别是INNER JOIN Kategorie没有指定加入条件,我觉得应该是Post_Kategorie.Kategorie_ID = Kategorie.ID

因此整个查询应该是这样的:

SELECT Post.headline, Post.date, Post.ID,
  CONCAT(
    "[", GROUP_CONCAT('{"name":"',Kategorie.name,'","id":',Kategorie.ID,'}'), "]"
  ) as "categorys"
FROM Post
INNER JOIN Post_Kategorie
  ON Post.ID = Post_Kategorie.post_ID
INNER JOIN Kategorie
  ON Post_Kategorie.Kategorie_ID = Kategorie.ID
WHERE Post.public = 1
  AND Post.type = 0
GROUP BY Post.headline, Post.date
HAVING MAX(CASE Post_Kategorie.kategorie_ID WHEN 2 THEN 1 ELSE 0 END) = 1
ORDER BY Post.date DESC
LIMIT 0, 20

Post_Kategorie.kategorie_ID = 2 条件已修改为 CASE 表达式并移至 HAVING 子句,并与 MAX() 聚合函数一起使用。其工作原理如下:

  • 如果帖子被标记为属于Kategorie.ID = 2 的一个或多个标签,CASE 表达式将返回 1,MAX 也将计算为 1。因此,所有组都将有效并保留在输出中。

  • 如果没有标记帖子的标签属于所述类别,则 CASE 表达式永远不会计算为 1,MAX 也不会。结果,整个组将被丢弃。

【讨论】:

  • 您说的有道理,但问题是,对于您的查询,categorys 列中唯一显示的类别是由 ID 指定的类别。我希望它包含帖子标记的所有类别。
  • @Lukas:那么您可能只需要删除Post_Kategorie.kategorie_ID = 2 条件。
  • 但是如何指定类别呢?所有列出的帖子都应该属于指定的类别,但我也想要一个包含它标记的所有类别的完整列表。
  • @Lukas:我想我现在明白了。请查看更新后的答案。
  • 非常好,解决了我的问题。我将阅读更多关于此的内容,但目前,非常感谢您。
猜你喜欢
  • 1970-01-01
  • 2020-11-04
  • 1970-01-01
  • 2016-08-05
  • 2011-02-22
  • 1970-01-01
  • 1970-01-01
  • 2020-06-05
  • 1970-01-01
相关资源
最近更新 更多