自联接总结
 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表:保存菜单的信息mid menuname pid url glyphicon 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表:用于存储用户与菜单的关联关系mid uid 1 1 2 1 3 2 mid:菜单的mid,表示该用户与哪些菜单有关联。
 
2. 查询解析
这条 SQL 查询实现了从 admin_menu 表中查询所有菜单数据,并通过两次自联接(INNER JOIN)以及与 rel_admin_user_menu 表的关联来筛选出需要的数据。
- 
admin_menu am和admin_menu am2的自联接:- 
这是一个自联接(
INNER JOIN),即同一个表admin_menu被连接了两次,分别用别名am和am2。 - 
连接条件是
am.pid = am2.mid,意味着am表中的每个菜单的父菜单(pid)将与am2表中的菜单的mid字段进行匹配。换句话说,查询通过菜单的父子关系(pid和mid)将父菜单与子菜单关联起来。 - 
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 submid、am.menuname AS submenuname、am.url AS suburl、am.glyphicon AS subglyphicon:从父菜单(am表)中选择字段,并且给这些字段起别名(submid,submenuname,suburl,subglyphicon),以便清晰地指示这些字段对应的是父菜单的数据。
 
3. 查询的实现原理
- 
自联接(
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 的子菜单。 
 - 如果有一个菜单 
 
 - 
 - 
联接条件:
am.pid = am2.mid:父菜单am的pid必须与子菜单am2的mid匹配,确保正确地关联父子菜单。ram.mid = am.mid:通过rel_admin_user_menu表中的mid字段与父菜单的mid进行匹配,确保只有与用户关联的菜单才会被选择。
 - 
最终结果:
- 这个查询会返回所有符合条件的父子菜单关系,且查询结果将包含父菜单和子菜单的信息。每个子菜单会显示在结果集中,父菜单的字段(如 
mid,menuname,url,glyphicon)会被赋予别名,例如submid,submenuname,suburl,subglyphicon,以避免字段名冲突。 
 - 这个查询会返回所有符合条件的父子菜单关系,且查询结果将包含父菜单和子菜单的信息。每个子菜单会显示在结果集中,父菜单的字段(如 
 
4. 查询返回的结果
假设查询返回如下结果:
| parent_mid | parent_menuname | sub_mid | sub_menuname | sub_url | sub_glyphicon | 
|---|---|---|---|---|---|
| 1 | 菜单管理 | 2 | 子菜单1 | /sub1 | icon2 | 
| 1 | 菜单管理 | 3 | 子菜单2 | /sub2 | icon3 | 
解释:
parent_mid和parent_menuname是从am表(父菜单)中获取的字段。sub_mid,sub_menuname,sub_url,sub_glyphicon是从am2表(子菜单)中获取的字段。am2表的每一行代表一个子菜单(如sub_mid = 2对应子菜单1,sub_mid = 3对应子菜单2),并且它们的父菜单(parent_mid = 1)通过am.pid = am2.mid关联。
5. 为什么会有父子菜单的重复?
如果查询返回的结果中存在重复的父菜单数据,可能是由于 INNER JOIN 关联导致的。假设一个父菜单有多个子菜单,并且与多个用户关联,查询结果会根据这些关系返回多个记录,且每条记录中可能会出现相同的父菜单数据。MyBatis 或其他 ORM 框架通常会根据 mid 来去重,避免重复创建父对象。
总结
- 这条查询通过 自联接 和 与关联表的联接 来实现父子菜单的关系。
 - 使用 
INNER JOIN来确保只查询有父菜单且与用户关联的菜单。 - 通过给父菜单和子菜单的字段起不同的别名,确保在结果中不会出现字段名冲突。
 - 父菜单和子菜单之间的关系通过 
pid和mid字段来建立,查询的结果返回父菜单与子菜单的联合数据。 
                    
                
                
            
        
浙公网安备 33010602011771号