
本文详解如何通过多表 left join 正确关联 blog、category 和 assigned 表,一次性获取每篇博客的标题、描述、发布时间、所属主分类及可为空的子分类名称。
本文详解如何通过多表 left join 正确关联 blog、category 和 assigned 表,一次性获取每篇博客的标题、描述、发布时间、所属主分类及可为空的子分类名称。
在实际博客系统中,分类结构常采用“主分类 → 子分类”的层级设计(如“Front End Development”为主类,“React”或“Vue”为其子类)。根据提供的数据库结构:
-
blog表存储博客基础信息; -
category表既表示主分类,也通过idsub字段递归指向自身(即子分类也存于同一张表); -
assigned表作为中间关系表,将博客与主分类(非子分类)关联。
因此,要提取每篇博客 + 其主分类名 + 对应的子分类名(允许为 NULL),必须使用 LEFT JOIN 链式关联,而非旧式逗号连接(ANSI-89 语法),原因如下:
- 逗号连接无法清晰表达层级依赖(如 category → subcategory 的自关联);
- LEFT JOIN 可确保即使某博客未分配子分类(即
category.idsub IS NULL),该博客记录仍会被保留,子分类字段显示为NULL; - WHERE 条件应置于最后,避免过早过滤掉待关联的空子类数据。
✅ 推荐写法(ANSI-92 标准,清晰、健壮、可维护):
SELECT b.idblog, b.title, b.description, b.date, c.categoryname AS categoryname, s.categoryname AS subcategoryname FROM blog b LEFT JOIN assigned a ON b.idblog = a.idblog LEFT JOIN category c ON a.idcategory = c.idcategory LEFT JOIN category s ON c.idsub = s.idcategory;
? 注意事项:
- 使用表别名(
b,a,c,s)提升可读性,并明确区分主分类表(c)与子分类表(s); - 所有
JOIN均为LEFT JOIN:保证即使某博客未被分配分类(assigned缺失)、或主分类未设子类(c.idsub IS NULL),博客记录仍完整返回; - 若需按特定主分类筛选(如仅查 “Front End Development”),可在末尾添加
WHERE c.categoryname = 'Front End Development';但注意:此条件会排除c为 NULL 的记录,若需包含未分类博客,应改用WHERE c.categoryname LIKE '%Front End%' OR c.categoryname IS NULL; -
category.idsub是外键,应确保其值确实存在于category.idcategory中(建议添加外键约束); - 避免在
ON子句中混入业务条件(如LIKE),否则可能导致意外的 JOIN 行为或性能下降。
? 总结:正确建模分类层级的关键在于理解 category 表的自引用设计,并通过两次 LEFT JOIN category 分别获取主类与子类。这是处理树状分类关系的基础 SQL 模式,适用于标签系统、商品类目、知识库分类等通用场景。

















