自联接总结

SELECT am2.*,am.mid as submid,am.menuname as submenuname,am.url as suburl,am.glyphicon as subglyphicon
from admin_menu am
inner join admin_menu am2 on am.pid = am2.mid

用父表pid(父级字段)到子表mid进行匹配,用父表数据进行逐行匹配

1. 表结构

假设有三个表:

  • admin_menu:保存菜单的信息

    midmenunamepidurlglyphicon
    1 菜单管理 0 /menu icon1
    2 子菜单1 1 /sub1 icon2
    3 子菜单2 1 /sub2 icon3
    4 用户管理 0 /user icon4
    • mid:菜单的主键,唯一标识每个菜单。
    • pid:父菜单的 mid,表示该菜单的上级菜单,pid = 0 表示没有父菜单。
  • rel_admin_user_menu:用于存储用户与菜单的关联关系

    miduid
    1 1
    2 1
    3 2
    • mid:菜单的 mid,表示该用户与哪些菜单有关联。

2. 查询解析

这条 SQL 查询实现了从 admin_menu 表中查询所有菜单数据,并通过两次自联接(INNER JOIN)以及与 rel_admin_user_menu 表的关联来筛选出需要的数据。

  • admin_menu amadmin_menu am2 的自联接

    • 这是一个自联接(INNER JOIN),即同一个表 admin_menu 被连接了两次,分别用别名 amam2

    • 连接条件是 am.pid = am2.mid,意味着 am 表中的每个菜单的父菜单(pid)将与 am2 表中的菜单的 mid 字段进行匹配。换句话说,查询通过菜单的父子关系(pidmid)将父菜单与子菜单关联起来。

    • am:表示的是父菜单(一级菜单)。

    • am2:表示的是子菜单(二级菜单)。

  • INNER JOIN rel_admin_user_menu ram

    • 这是与 rel_admin_user_menu 表的联接,用来筛选出与用户相关的菜单。
    • 连接条件是 ram.mid = am.mid,这意味着 该菜单必须在 rel_admin_user_menu 表中与某个用户关联,即该菜单必须是某个用户可访问的菜单。
  • SELECT 子句

    • am2.*:选择 am2 表中的所有字段(即子菜单的所有字段)。
    • am.mid AS submidam.menuname AS submenunameam.url AS suburlam.glyphicon AS subglyphicon:从父菜单(am 表)中选择字段,并且给这些字段起别名(submid, submenuname, suburl, subglyphicon),以便清晰地指示这些字段对应的是父菜单的数据。

3. 查询的实现原理

  1. 自联接(INNER JOIN

    • SQL 中的自联接是通过给同一个表设置两个不同的别名来实现的。在这个查询中,admin_menu am 代表父菜单,admin_menu am2 代表子菜单,am.pid = am2.mid 使得父菜单与子菜单根据父菜单的 pid 字段和子菜单的 mid 字段建立联系。

    • 例如:

      • 如果有一个菜单 mid = 1(菜单管理),其 pid = 0,表示它是父菜单。
      • 如果另一个菜单 mid = 2(子菜单1),其 pid = 1,表示它是父菜单 1 的子菜单。
  2. 联接条件

    • am.pid = am2.mid:父菜单 ampid 必须与子菜单 am2mid 匹配,确保正确地关联父子菜单。
    • ram.mid = am.mid:通过 rel_admin_user_menu 表中的 mid 字段与父菜单的 mid 进行匹配,确保只有与用户关联的菜单才会被选择。
  3. 最终结果

    • 这个查询会返回所有符合条件的父子菜单关系,且查询结果将包含父菜单和子菜单的信息。每个子菜单会显示在结果集中,父菜单的字段(如 mid, menuname, url, glyphicon)会被赋予别名,例如 submid, submenuname, suburl, subglyphicon,以避免字段名冲突。

4. 查询返回的结果

假设查询返回如下结果:

parent_midparent_menunamesub_midsub_menunamesub_urlsub_glyphicon
1 菜单管理 2 子菜单1 /sub1 icon2
1 菜单管理 3 子菜单2 /sub2 icon3

解释:

  • parent_midparent_menuname 是从 am 表(父菜单)中获取的字段。
  • sub_mid, sub_menuname, sub_url, sub_glyphicon 是从 am2 表(子菜单)中获取的字段。
  • am2 表的每一行代表一个子菜单(如 sub_mid = 2 对应 子菜单1sub_mid = 3 对应 子菜单2),并且它们的父菜单(parent_mid = 1)通过 am.pid = am2.mid 关联。

5. 为什么会有父子菜单的重复?

如果查询返回的结果中存在重复的父菜单数据,可能是由于 INNER JOIN 关联导致的。假设一个父菜单有多个子菜单,并且与多个用户关联,查询结果会根据这些关系返回多个记录,且每条记录中可能会出现相同的父菜单数据。MyBatis 或其他 ORM 框架通常会根据 mid 来去重,避免重复创建父对象。

总结

  • 这条查询通过 自联接与关联表的联接 来实现父子菜单的关系。
  • 使用 INNER JOIN 来确保只查询有父菜单且与用户关联的菜单。
  • 通过给父菜单和子菜单的字段起不同的别名,确保在结果中不会出现字段名冲突。
  • 父菜单和子菜单之间的关系通过 pidmid 字段来建立,查询的结果返回父菜单与子菜单的联合数据。
posted @   langpo  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· Trae初体验
点击右上角即可分享
微信分享提示