获取特定类别的所有帖子

时间:2011-07-03 09:54:22

标签: mysql sql select join

情况

正如你们中的一些人可能已经从我之前的问题中了解到的那样,我目前正在开发一个博客系统。

这一次,我坚持要获取特定类别的所有帖子及其类别。

数据库

以下是用于创建三个必需表的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条件下,但我不知道在哪里。请指出我正确的方向。

1 个答案:

答案 0 :(得分: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也不会评估。结果,整个组都将被丢弃。