精华内容
下载资源
问答
  • 主要介绍了MongoDB多表关联查询操作,结合实例形式详细分析了MongoDB数据库实现多表关联查询的相关原理与实现技巧,需要的朋友可以参考下
  • 主要介绍了MyBatis-Plus多表联合查询并且分页(3联合),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 主要介绍了Spring boot2基于Mybatis实现多表关联查询,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 主要介绍了Mysql多表联合查询效率分析及优化,需要的朋友可以参考下
  • NoSql的多表关联一直是比较复杂的问题,下面这篇文章主要给大家介绍了关于MongoDB中多表关联查询($lookup)的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
  • thinkphp中的多表关联查询的实例详解  在进行后端管理系统的编程的时候一般会使用框架来进行页面的快速搭建,我最近使用比较的就是thinkphp框架,thinkphp框架的应用其实就是把前端和后端进行分割管理,前端用户...
  • 多表联合查询

    2012-09-16 21:46:59
    多表联合查询的Hibernate应用
  • Mysql多表联合查询

    2015-11-11 15:29:12
    MySql,多表联合查询加AS语句,多余的就不说了,自己看,绝对简单!
  • Mysql学习中 ,单表查询每个人都很...但是多表之间的关联查询对于初学者是很难掌握的,以下是我学习中,结合老师所讲例子作的总结,主要就是三张表的关联查询。还包括group by操作。Join on;left join on;group by。
  • 主要介绍了mysql实现多表关联统计(子查询统计),结合具体案例形式分析了mysql多表关联统计的原理、实现方法及相关操作注意事项,需要的朋友可以参考下
  • mysql多表联合查询

    2013-11-04 22:36:25
    mysql多表联合查询 连接的约束条件 MySQL如何优化LEFT JOIN和RIGHT JOIN
  • Sequelize多表联合查询案例

    千次阅读 2021-05-12 11:12:06
    查询Match中的user_id,report_comment,以及job_history_id所关联的JOB中的job_link,在前端显示。 三、Code: 1. 后端 首先要建立两个关联: MatchScoreReportModel.belongsTo(JobHistoryModel, { foreign...

    一、Table:

    现在有两个表,A和B,关联关系:
    MATCH表中的job_history_id与JOB_HISTORY表中的id相关联。
    在这里插入图片描述

    二、需求:

    查询Match表中的user_id,report_comment,以及job_history_id所关联的JOB表中的job_link,在前端显示。

    三、Code:

    1. 后端

    首先要建立两个表的关联:

    MatchScoreReportModel.belongsTo(JobHistoryModel, {
      foreignKey: 'job_history_id',
      targetKey: 'id',
    });
    

    在这里插入图片描述
    然后开始查询,中间用include进行连接:

    const { rows, count } = await MatchScoreReport.findAndCountAll({
      attributes: ['user_id', 'report_comment'],
      ...
      include: [
        {
          attributes: ['job_link'],
          model: JobHistoryModel,
        },
      ],
      ...
    });
    return {
      rows,
      count,
    };
    

    中间的…,指的是你的一些其他的条件。核心就是其中的include: []
    这样就能查询出来我们想要的三个字段:user_id,report_comment,job_link

    但是我们看一下拼接出来的SQL,以及查询出来的结果:

    SELECT `MATCH_SCORE_REPORT`.`user_id`,
           `MATCH_SCORE_REPORT`.`report_comment`,
           `JOB_HISTORY`.`job_link` AS `JOB_HISTORY.job_link`
    FROM `MATCH_SCORE_REPORT` AS `MATCH_SCORE_REPORT`
             LEFT OUTER JOIN `JOB_HISTORY` AS `JOB_HISTORY` ON `MATCH_SCORE_REPORT`.`job_history_id` = `JOB_HISTORY`.`id`;
    

    我们可以看到,它是给job_link起了一个别名,叫做JOB_HISTORY.job_link
    返回的结果部分截图(数据脱敏处理):
    在这里插入图片描述
    这样的话,前端得到的也是一个带有JOB_HISTORY.前缀的结果,
    所以前端进行结果的遍历和处理的时候,也需要额外多做一些处理:

    2. 前端

    首先是接口的定义,对应的属性使用''包裹起来。

    interface ReportComments {
      user_id: string;
      report_comment: string;
      'JOB_HISTORY.job_link': string;
    }
    

    其次是遍历的时候,根据不同的框架可能需要自己调整获取的方式,但是直接xxx.xxx.xxx是会报错的,不过大概就那么几种方式,试试就能试出来:

    我的情况:
    (注意其中的不同,original.report_commentoriginal['JOB_HISTORY.job_link']

    {
      Header: 'Comment',
      Cell({ original }: { original: ReportComments }) {
        return <div className="p-2">{original.report_comment}</div>;
      },
    },
    {
      Header: 'JobURL',
      Cell({ original }: { original: ReportComments }) {
        return <div className="p-2">{original['JOB_HISTORY.job_link']}</div>;
      },
    },
    

    另一位大佬的情况, 我贴上地址和截图:
    https://blog.csdn.net/lvyuan1234/article/details/86727703
    在这里插入图片描述
    大同小异,简单一弄就好了。

    四、后记:

    有人可能会有疑问,我其实也有这个疑问,那个多余的前缀我们能不能去掉,我找了半天没找到办法,看到有个帖子说,目前还不支持,所以我就放弃了。如果实在需要,就可以自己写SQL。
    不知道未来的版本是否会支持,或者是不是已经存在好的办法,我没搜到,如果有大佬知道,还望不吝赐教!

    展开全文
  • 【MySQL】多表联合查询、连接查询、子查询

    万次阅读 多人点赞 2019-06-03 17:08:20
    联合查询的意义: 查询同一张,但是需求不同 如查询学生信息, 男生身高升序, 女生身高降序 多表查询: 张表的结构是完全一样的,保存的数据(结构)也是一样的. 联合查询order by的使用 在联合查询中: order by不能...

    【1】连接查询

    连接查询的意义: 在用户查看数据的时候,需要显示的数据来自多张表.

    内连接查询

    内连接查询是最常见的连接查询,内连接查询可以查询两张或两张以上的表

    内连接:[inner] join:从左表中取出每一条记录,去右表中与所有的记录进行匹配: 匹配必须是某个条件在左表中与右表中相同最终才会保留结果,否则不保留.

    基本语法:左表 [inner] join 右表 on 左表.字段 = 右表.字段;
    on表示连接条件: 条件字段就是代表相同的业务含义(如my_student.c_id和my_class.id)

    当两个表中存在相同意义的字段的时候,就可以通过该字段来连接查询这两个表,当该字段的值相同时就可以查出该记录。

    内连接可以没有连接条件: 没有on之后的内容,这个时候系统会保留所有结果。

    例:

    select a.id,a.name,a.sex,b.country,b.city,b.street 
    from student a 
    join addr b 
    on a.addrid=b.addrid;
    

    在这里插入图片描述

    外连接查询

    以某张表为主,取出里面的所有记录, 然后每条与另外一张表进行连接: 不管能不能匹配上条件,最终都会保留: 能匹配,正确保留; 不能匹配,其他表的字段都置空NULL。

    左连接

    left join: 左外连接(左连接), 以左表为主表
    基本语法: from 左表 left join 右表 on 左表.字段 = 右表.字段;

    左表不管能不能匹配上条件,最终都会保留:能匹配,正确的保留; 若不能匹配,右表的字段都置NULL。

    例:

    select a.id,a.name,a.addrid,b.country,b.city
    from student a left join addr b
    on a.addrid=b.addrid;
    

    在这里插入图片描述

    右连接

    right join: 右外连接(右连接), 以右表为主表
    基本语法: from 左表 right join 右表 on 左表.字段 = 右表.字段;
    右表不管能不能匹配上条件,最终都会保留:能匹配,正确的保留; 若不能匹配,左表的字段都置NULL。

    例:

    select a.id,a.name,a.addrid,b.country,b.city
    from student a right join addr b
    on a.addrid=b.addrid;
    

    在这里插入图片描述

    【2】联合查询

    联合查询
    联合查询结果是将多个select语句的查询结果合并到一块因为在某种情况下需要将几个select语句查询的结果合并起来显示。比如现在需要查询两个公司的所有员工的信息,这就需要从甲公司查询所有员工信息,再从乙公司查询所有的员工信息,然后将两次的查询结果进行合并。
    可以使用unionunion all关键字进行操作

    语法格式如下:

    select 语句1
    union[union 选项]
    select 语句2
    union|[union 选项]
    select 语句n
    

    其中union选项有两个选项可选
    all:表示无论重复都输出
    distinct: 去重(整个重复)(默认的)

    select *from addr
    union all
    select *from addr;
    

    在这里插入图片描述

    select id,addrid 
    from addr 
    union all 
    select id,addrid 
    from student;
    

    在这里插入图片描述联合查询只要求字段一样, 跟数据类型和顺序无关

    select id,addrid,sex,score 
    from student 
    union all 
    select sex,addrid,id,score 
    from student;
    

    在这里插入图片描述
    联合查询的意义:

    1. 查询同一张表,但是需求不同 如查询学生信息, 男生身高升序, 女生身高降序
    2. 多表查询: 多张表的结构是完全一样的,保存的数据(结构)也是一样的.

    联合查询order by的使用
    在联合查询中: order by不能直接使用(不能出现两次),需要对查询语句使用括号才行;

    select *from student 
    where sex="woman" 
    order by score
    union
    select *from 
    student where sex="man" 
    order by score;
    

    这种情况是会报错的。因为语句中不允许出现两个order by。

    select *from student where sex="woman" 
    union
    select *from student where sex="man" order by score;
    

    如果是上边这样只出现一次他的意义就是等合并完成之后再进行排序就没有任何意义了,因为又把前边sex分好的类打乱了

    (select *from student 
    where sex="woman" 
    order by score )
    union
    (select *from 
    student where sex="man" 
    order by score;)
    

    这种方式的目的是为了让两个结果集先分别order by,然后再对两个结果集进行union。但是你会发现这种方式虽然不报错了,但是两个order by并没有产生最后的效果,所以应该改成如下:

    select *from
    (select *from student 
    where sex="woman" 
    order by score)student
    union
    select *from
    (select *from student 
    where sex="man" 
    order by score)student ;
    

    也就是说,order by不能直接出现在union的子句中,但是可以出现在子句的子句中。
    在这里插入图片描述

    【3】子查询

    通常我们在查询的SQL中嵌套查询,称为子查询。子查询通常会使复杂的查询变得简单,但是相关的子查询要对基础表的每一条数据都进行子查询的动作,所以当表单中数据过大时,一定要慎重选择

    带in关键字的子查询

    使用in关键字可以将原表中特定列的值与子查询返回的结果集中的值进行比较
    如果某行的特定列的值存在,则在select语句的查询结果中就包含这一行。

    例:查询成绩大于80的学生的所有信息,
    先在子查询中查出成绩大于80的结果集,然后将原成绩表中的成绩与结果集进行比较,如果存在,就输出这条学生的记录。

    select *
    from student 
    where score in
    (select score from student where score>80);
    

    在这里插入图片描述

    带比较运算符的子查询

    如果可以确认子查询返回的结果只包含一个单值,那么可以直接使用比较运算符连接子查询。
    经常使用的比较运算符包括等于(=)、不等于(<>或!=)、小于(<)、大于(>)、小于等于(<=)和大于等于(>=)。

    select *
    from student 
    where score> 
    (select score 
    from scholarship
    where dengji=1);
    

    查询奖学金等级为1的学生信息

    带exists的子查询

    exists: 是否存在的意思, exists子查询就是用来判断某些条件是否满足(跨表),
    exists是接在where之后
    exists返回的结果只有0和1.

    例:如果存在成绩大于90的人则列出整个表的记录

    select *
    from student 
    where exists
    (select *from student where score>90);
    

    在这里插入图片描述

    带any关键字的子查询

    any关键字表示满足其中的任意一个条件使用any关键字时,只要满足内层查询语句结果的的任意一个,就可以通过该条件来执行外层查询语句。

    select *
    from student 
    where addrid<any
    (select addrid 
    from addr);
    

    在这里插入图片描述

    带all关键字的子查询

    all和any刚好是相反的,all关键字表示满足所有结果使用all关键字,要满足内层查询语句的所有结果,才可以通过该条件来执行外层查询语句。

    select *
    from student 
    where addrid>all
    (select addrid 
    from addr);
    

    在这里插入图片描述

    展开全文
  • 主要介绍了Mybatis基于注解实现多表查询功能,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
  • Mybatis的多表关联查询

    千次阅读 多人点赞 2021-02-12 23:46:03
    Mybatis的多表关联查询)项目目录结构实现 Role 到 User 业务要求用户与角色的关系模型编写角色实体类编写 Role 持久层接口实现的 SQL 语句编写映射文件测试代码实现 User 到 Role 的业务要求...

    mybatis中的多表查询:
    
    	示例:用户和角色
    		一个用户可以有多个角色
    		一个角色可以赋予多个用户
    	步骤:
    		1、建立两张表:用户表,角色表
    			让用户表和角色表具有多对多的关系。需要使用中间表,中间表中包含各自的主键,在中间表中是外键。
    		2、建立两个实体类:用户实体类和角色实体类
    			让用户和角色的实体类能体现出来多对多的关系
    			各自包含对方一个集合引用
    		3、建立两个配置文件
    			用户的配置文件
    			角色的配置文件
    		4、实现配置:
    			当我们查询用户时,可以同时得到用户所包含的角色信息
    			当我们查询角色时,可以同时得到角色的所赋予的用户信息
    

    项目目录结构

    在这里插入图片描述

    实现 Role 到 User 多对多

    多对多关系其实我们看成是双向的一对多关系。

    业务要求

    需求:
    当我们查询角色时,可以同时得到角色的所赋予的用户信息。
    分析:
    查询角色我们需要用到Role表,但角色分配的用户的信息我们并不能直接找到用户信息,而是要通过中间表(USER_ROLE 表)才能关联到用户信息。

    用户与角色的关系模型

    用户与角色的多对多关系模型如下:
    在这里插入图片描述

    角色表:
    在这里插入图片描述
    用户表:
    在这里插入图片描述
    用户角色中间表:
    在这里插入图片描述

    编写角色实体类

    Role:

    package com.keafmd.domain;
    
    import java.io.Serializable;
    import java.util.List;
    
    /**
     * Keafmd
     *
     * @ClassName: Role
     * @Description: 角色实体类
     * @author: 牛哄哄的柯南
     * @date: 2021-02-12 16:45
     */
    public class Role implements Serializable {
    
        private Integer roleId;
        private String roleName;
        private String roleDesc;
    
        //多对多的关系映射
        private List<User> users;
    
        public List<User> getUsers() {
            return users;
        }
    
        public void setUsers(List<User> users) {
            this.users = users;
        }
    
        public Integer getRoleId() {
            return roleId;
        }
    
        public void setRoleId(Integer roleId) {
            this.roleId = roleId;
        }
    
        public String getRoleName() {
            return roleName;
        }
    
        public void setRoleName(String roleName) {
            this.roleName = roleName;
        }
    
        public String getRoleDesc() {
            return roleDesc;
        }
    
        public void setRoleDesc(String roleDesc) {
            this.roleDesc = roleDesc;
        }
    
        @Override
        public String toString() {
            return "Role{" +
                    "roleId=" + roleId +
                    ", roleName='" + roleName + '\'' +
                    ", roleDesc='" + roleDesc + '\'' +
                    '}';
        }
    }
    

    编写 Role 持久层接口

    IRoleDao:

    package com.keafmd.dao;
    import com.keafmd.domain.Role;
    import java.util.List;
    
    /**
     * Keafmd
     *
     * @ClassName: IRoleDao
     * @Description:
     * @author: 牛哄哄的柯南
     * @date: 2021-02-12 19:01
     */
    
    public interface IRoleDao {
    
        /**
         * 查询所有角色
         * @return
         */
        List<Role> findAll();
    
    }
    

    实现的 SQL 语句

    select u.*,r.id as rid ,r.role_name ,r.role_desc from role r  
    left outer join user_role ur on r.id = ur.rid  
    left outer join user u on u.id=ur.uid 
    

    执行结果:
    在这里插入图片描述

    注意:sql语句换行的时候最好在每行的末尾或开头添加空格,这样可以防止合并成一行时发生错误。

    编写映射文件

    IRoleDao.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.keafmd.dao.IRoleDao">
    
        <!--定义role表的resultmap-->
        <resultMap id="roleMap" type="role">
            <id property="roleId" column="rid"></id>
            <result property="roleName" column="role_name"></result>
            <result property="roleDesc" column="role_desc"></result>
            <collection property="users" ofType="user">
                <id column="id" property="id"></id>
                <result column="username" property="username"></result>
                <result column="address" property="address"></result>
                <result column="sex" property="sex"></result>
                <result column="birthday" property="birthday"></result>
            </collection>
        </resultMap>
    
        <!--查询所有-->
        <select id="findAll" resultMap="roleMap">
            select u.*,r.id as rid ,r.role_name ,r.role_desc from role r
            left outer join user_role ur on r.id = ur.rid
            left outer join user u on u.id=ur.uid
        </select>
    
    </mapper>
    

    测试代码

    RoleTest:

    package com.keafmd.test;
    
    import com.keafmd.dao.IRoleDao;
    import com.keafmd.dao.IUserDao;
    import com.keafmd.domain.Role;
    import com.keafmd.domain.User;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    
    import java.io.InputStream;
    import java.util.List;
    
    /**
     * Keafmd
     *
     * @ClassName: MybatisTest
     * @Description: 测试类,测试crud操作
     * @author: 牛哄哄的柯南
     * @date: 2021-02-08 15:24
     */
    public class RoleTest {
    
        private InputStream in;
        private SqlSession sqlsession;
        private IRoleDao roleDao;
    
        @Before // 用于在测试方法执行前执行
        public void init()throws Exception{
            //1.读取配置文件,生成字节输入流
            in = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.创建SqlSessionFactory工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(in);
            //3.使用工厂生产SqlSession对象
            sqlsession = factory.openSession(); //里面写个true,下面每次就不用了写 sqlsession.commit(); 了
            //4.使用SqlSession创建Dao接口的代理对象
            roleDao = sqlsession.getMapper(IRoleDao.class);
        }
    
        @After // 用于在测试方法执行后执行
        public void destory() throws Exception{
            //提交事务
            sqlsession.commit();
            //6.释放资源
            sqlsession.close();
            in.close();
        }
    
    
    
        /**
         * 查询所有
         * @throws Exception
         */
        @Test
        public void testFindAll() {
            List<Role> roles = roleDao.findAll();
            for (Role role : roles) {
                System.out.println("--------每个角色的信息---------");
                System.out.println(role);
                System.out.println(role.getUsers());
               
            }
        }
    
    }
    

    运行结果:

    2021-02-13 00:05:47,481 349    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Opening JDBC Connection
    2021-02-13 00:05:47,784 652    [           main] DEBUG source.pooled.PooledDataSource  - Created connection 1027007693.
    2021-02-13 00:05:47,784 652    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3d36e4cd]
    2021-02-13 00:05:47,791 659    [           main] DEBUG om.keafmd.dao.IRoleDao.findAll  - ==>  Preparing: select u.*,r.id as rid ,r.role_name ,r.role_desc from role r left outer join user_role ur on r.id = ur.rid left outer join user u on u.id=ur.uid
    2021-02-13 00:05:47,842 710    [           main] DEBUG om.keafmd.dao.IRoleDao.findAll  - ==> Parameters: 
    2021-02-13 00:05:47,869 737    [           main] DEBUG om.keafmd.dao.IRoleDao.findAll  - <==      Total: 4
    --------每个角色的信息---------
    Role{roleId=1, roleName='院长', roleDesc='管理整个学院'}
    [User{id=41, username='老王', sex='男', address='北京', birthday=Tue Feb 27 17:47:08 CST 2018}, User{id=45, username='新一', sex='男', address='北京', birthday=Sun Mar 04 12:04:06 CST 2018}]
    --------每个角色的信息---------
    Role{roleId=2, roleName='总裁', roleDesc='管理整个公司'}
    [User{id=41, username='老王', sex='男', address='北京', birthday=Tue Feb 27 17:47:08 CST 2018}]
    --------每个角色的信息---------
    Role{roleId=3, roleName='校长', roleDesc='管理整个学校'}
    []
    2021-02-13 00:05:47,871 739    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3d36e4cd]
    2021-02-13 00:05:47,872 740    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3d36e4cd]
    2021-02-13 00:05:47,872 740    [           main] DEBUG source.pooled.PooledDataSource  - Returned connection 1027007693 to pool.
    
    Process finished with exit code 0
    

    实现 User 到 Role 的多对多

    业务要求

    需求:
    当我们查询用户时,可以同时得到用户所包含的角色信息。

    分析:
    相比上面的实现 Role 到 User 多对多,主要变化就是sql语句的变化。

    编写用户实体类

    User:

    package com.keafmd.domain;
    
    import java.io.Serializable;
    import java.util.Date;
    import java.util.List;
    
    /**
     * Keafmd
     *
     * @ClassName: User
     * @Description:
     * @author: 牛哄哄的柯南
     * @date: 2021-02-08 15:16
     */
    
    public class User implements Serializable {
        private Integer id;
        private String username;
        private String sex;
        private String address;
        private Date birthday;
    
        //多对多的关系映射,一个用户可以具备多个角色
        private List<Role> roles;
    
        public List<Role> getRoles() {
            return roles;
        }
    
        public void setRoles(List<Role> roles) {
            this.roles = roles;
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", sex='" + sex + '\'' +
                    ", address='" + address + '\'' +
                    ", birthday=" + birthday +
                    '}';
        }
    }
    

    编写 User持久层接口

    IUserDao:

    package com.keafmd.dao;
    
    import com.keafmd.domain.User;
    
    import java.util.List;
    
    /**
     * Keafmd
     *
     * @ClassName: IUserDao
     * @Description: 用户的持久层接口
     * @author: 牛哄哄的柯南
     * @date: 2021-02-06 19:29
     */
    
    public interface IUserDao {
        /**
         * 查询所有用户,同时获取到用户下所有账户的信息
         * @return
         */
        List<User> findAll();
    
    }
    

    实现的 SQL 语句

       select u.*,r.id as rid ,r.role_name ,r.role_desc from user u 
       left outer join user_role ur on u.id = ur.uid 
       left outer join role r on r.id=ur.rid 
    

    执行结果:
    在这里插入图片描述

    编写映射文件

    IUserDao.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.keafmd.dao.IUserDao">
    
        <!--定义User的resultMap-->
        <resultMap id="userMap" type="user">
            <id property="id" column="id"></id>
            <result property="username" column="username"></result>
            <result property="address" column="address"></result>
            <result property="sex" column="sex"></result>
            <result property="birthday" column="birthday"></result>
            <!--配置角色集合的映射-->
            <collection property="roles" ofType="role">
                <id property="roleId" column="rid"></id>
                <result property="roleName" column="role_name"></result>
                <result property="roleDesc" column="role_desc"></result>
            </collection>
    
        </resultMap>
    
        <!--配置查询所有-->
        <select id="findAll" resultMap="userMap">
            select u.*,r.id as rid ,r.role_name ,r.role_desc from user u
            left outer join user_role ur on u.id = ur.uid
            left outer join role r on r.id=ur.rid
    
        </select>
    
    </mapper>
    

    测试代码

    UserTest :

    package com.keafmd.test;
    
    import com.keafmd.dao.IUserDao;
    import com.keafmd.domain.User;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    
    import java.io.InputStream;
    import java.util.List;
    
    /**
     * Keafmd
     *
     * @ClassName: MybatisTest
     * @Description: 测试类,测试crud操作
     * @author: 牛哄哄的柯南
     * @date: 2021-02-08 15:24
     */
    public class UserTest {
    
        private InputStream in;
        private SqlSession sqlsession;
        private IUserDao userDao;
    
        @Before // 用于在测试方法执行前执行
        public void init()throws Exception{
            //1.读取配置文件,生成字节输入流
            in = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.创建SqlSessionFactory工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(in);
            //3.使用工厂生产SqlSession对象
            sqlsession = factory.openSession(); //里面写个true,下面每次就不用了写 sqlsession.commit(); 了
            //4.使用SqlSession创建Dao接口的代理对象
            userDao = sqlsession.getMapper(IUserDao.class);
        }
    
        @After // 用于在测试方法执行后执行
        public void destory() throws Exception{
            //提交事务
            sqlsession.commit();
            //6.释放资源
            sqlsession.close();
            in.close();
        }
    
    
    
        /**
         * 查询所有
         * @throws Exception
         */
        @Test
        public void testFindAll() {
            List<User> users = userDao.findAll();
            for (User user : users) {
                System.out.println("--------每个用户的信息---------");
                System.out.println(user);
                System.out.println(user.getRoles());
            }
        }
    
    }
    

    运行结果:

    2021-02-13 00:17:32,971 422    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Opening JDBC Connection
    2021-02-13 00:17:33,275 726    [           main] DEBUG source.pooled.PooledDataSource  - Created connection 1027007693.
    2021-02-13 00:17:33,275 726    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3d36e4cd]
    2021-02-13 00:17:33,280 731    [           main] DEBUG om.keafmd.dao.IUserDao.findAll  - ==>  Preparing: select u.*,r.id as rid ,r.role_name ,r.role_desc from user u left outer join user_role ur on u.id = ur.uid left outer join role r on r.id=ur.rid
    2021-02-13 00:17:33,319 770    [           main] DEBUG om.keafmd.dao.IUserDao.findAll  - ==> Parameters: 
    2021-02-13 00:17:33,343 794    [           main] DEBUG om.keafmd.dao.IUserDao.findAll  - <==      Total: 10
    --------每个用户的信息---------
    User{id=41, username='老王', sex='男', address='北京', birthday=Tue Feb 27 17:47:08 CST 2018}
    [Role{roleId=1, roleName='院长', roleDesc='管理整个学院'}, Role{roleId=2, roleName='总裁', roleDesc='管理整个公司'}]
    --------每个用户的信息---------
    User{id=42, username='update', sex='男', address='XXXXXXX', birthday=Mon Feb 08 19:37:31 CST 2021}
    []
    --------每个用户的信息---------
    User{id=43, username='小二王', sex='女', address='北京', birthday=Sun Mar 04 11:34:34 CST 2018}
    []
    --------每个用户的信息---------
    User{id=45, username='新一', sex='男', address='北京', birthday=Sun Mar 04 12:04:06 CST 2018}
    [Role{roleId=1, roleName='院长', roleDesc='管理整个学院'}]
    --------每个用户的信息---------
    User{id=50, username='Keafmd', sex='男', address='XXXXXXX', birthday=Mon Feb 08 15:44:01 CST 2021}
    []
    --------每个用户的信息---------
    User{id=51, username='update DAO', sex='男', address='XXXXXXX', birthday=Tue Feb 09 11:31:38 CST 2021}
    []
    --------每个用户的信息---------
    User{id=52, username='Keafmd DAO', sex='男', address='XXXXXXX', birthday=Tue Feb 09 11:29:41 CST 2021}
    []
    --------每个用户的信息---------
    User{id=53, username='Keafmd laset insertid 1', sex='男', address='XXXXXXX', birthday=Fri Feb 12 20:53:46 CST 2021}
    []
    --------每个用户的信息---------
    User{id=54, username='Keafmd laset insertid 2 auto', sex='男', address='XXXXXXX', birthday=Fri Feb 12 21:02:12 CST 2021}
    []
    2021-02-13 00:17:33,345 796    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3d36e4cd]
    2021-02-13 00:17:33,346 797    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3d36e4cd]
    2021-02-13 00:17:33,346 797    [           main] DEBUG source.pooled.PooledDataSource  - Returned connection 1027007693 to pool.
    
    Process finished with exit code 0
    

    以上就是Mybatis的多表关联查询(多对多)的全部内容。

    看完如果对你有帮助,感谢点赞支持!
    如果你是电脑端的话,看到右下角的 “一键三连” 了吗,没错点它[哈哈]

    在这里插入图片描述

    加油!

    共同努力!

    Keafmd

    展开全文
  • Spring Data Mongodb多表关联查询

    万次阅读 2018-12-27 16:19:29
    Spring Data Mongodb使用$lookup实现多表关联查询Spring Data Mongodb多表关联查询前言一、实例1、数据准备2、 一对一:两表关联查询3、一对一:多表关联查询4、一对:关联查询二、讲道理1、自定义...

    Spring Data Mongodb多表关联查询

    前言

    额瑞巴蒂,好。

    最近公司的项目采用Mongodb作为数据库,我也是一头雾水,因为MongoDB是最近几年才火起来,没有什么太多的学习资料。只有看Mongodb官网,Spring Data Mongodb官网文档,看起也比较吃力。所以对Mongodb也是摸着石头过河,有什么不对的地方还请各位老铁多多指教。

    开始吧!

    一、实例

    为了演示对象间一对一、一对多关系,现在创建三张表:公司(Company)、部门(Department)、员工(Employee)

    1、数据准备

    // 公司
    public class Company {
        @Id
        private String id;
    
        private String companyName;
    
        private String mobile;
    }
    
    // 部门
    public class Department {
        @Id
        private String id;
    
        private String departmentName;
    
        @DBRef
        private Company company;
    
        @DBRef
        private List<Employee> employeeList;
    }
    
    // 员工
    public class Employee {
        @Id
        private String id;
        
        private String employeeName;
        
        private String phone;
        
        @DBRef
        private Department department;
    }
    

    创建测试所需的数据:

    	@Autowired
        private MongoTemplate mongoTemplate;
    
        @Test
        public void initData() {
            // 公司
            Company company = new Company();
            company.setCompanyName("XXX公司");
            company.setMobile("023-66668888");
            mongoTemplate.save(company);
    
            // 部门
            Department department = new Department();
            department.setDepartmentName("XXX信息开发系统");
            department.setCompany(company);
            department.setEmployeeList(Collections.emptyList());
            mongoTemplate.save(department);
    
            // 员工
            List<Employee> employeeList = new ArrayList<>();
            Employee employee1 = new Employee();
            employee1.setEmployeeName("张一");
            employee1.setPhone("159228359xx");
            employee1.setDepartment(department);
            employeeList.add(employee1);
    
            Employee employee2 = new Employee();
            employee2.setEmployeeName("张二");
            employee2.setPhone("159228358xx");
            employee2.setDepartment(department);
            employeeList.add(employee2);
            mongoTemplate.insert(employeeList, Employee.class);
    
            department.setEmployeeList(employeeList);
            mongoTemplate.save(department);
        }
    

    2、 一对一:两表关联查询

    RemoveDollarOperation :自定义的Mongodb aggregation管道操作,在稍后的内容中会介绍

       /**
         * 员工表关联部门表
         */
        @Test
        public void twoTableQuery() {
                    // 1、消除@DBRef引用对象中的"$id"的"$"符号
            RemoveDollarOperation removeDollarOperation = new RemoveDollarOperation("newDepartmentFieldName", "department");
    
            // 2、使用mongodb $lookup实现左连接部门表
            LookupOperation lookupOperation = LookupOperation.newLookup().from("department")
                    .localField("newDepartmentFieldName.id").foreignField("_id").as("newDepartment");
    
            // $match条件筛选
    		// MatchOperation matchOperation = new MatchOperation(Criteria.where("newDepartment.departmentName").is("信息开发系统"));
            
            // 3、Aggregation管道操作(还可以加入$match、$project等其他管道操作,但是得注意先后顺序)
            TypedAggregation aggregation = Aggregation.newAggregation(Employee.class, removeDollarOperation, lookupOperation);
    		// TypedAggregation aggregation = Aggregation.newAggregation(Employee.class, removeDollarOperation, lookupOperation, matchOperation);
            AggregationResults<Document> results = mongoTemplate.aggregate(aggregation, Document.class);
    
            System.out.println(JSONArray.toJSONString(results.getMappedResults()));
        }
    

    3、一对一:多表关联查询

    /**
      * 员工表关联部门表,部门表关联公司表
      */
    @Test
    public void threeTableQuery() {
            // 1、消除@DBRef引用对象中的"$id"的"$"符号
            RemoveDollarOperation removeDollarOperation1 = new RemoveDollarOperation("newDepartmentFieldName", "department");
    
            // 2、使用mongodb $lookup实现左连接部门表
            LookupOperation lookupOperation1 = LookupOperation.newLookup().from("department")
                    .localField("newDepartmentFieldName.id").foreignField("_id").as("newDepartment");
    
            // 3、使用$unwind展平步骤二中的左连接的department表的"newDepartment"
            UnwindOperation unwindOperation = new UnwindOperation(Fields.field("$newDepartment"));
    
            // 4、消除@DBRef引用对象中的"$id"的"$"符号
            RemoveDollarOperation removeDollarOperation2 = new RemoveDollarOperation("newCompanyFieldName", "newDepartment.company");
    
            // 5、使用mongodb $lookup实现左连接公司表
            LookupOperation lookupOperation2 = LookupOperation.newLookup().from("company")
                    .localField("newCompanyFieldName.id").foreignField("_id").as("newCompany");
    
            MatchOperation matchOperation = new MatchOperation(Criteria.where("newCompany.companyName").is("XXX公司"));
    
            // 4、Aggregation管道操作(还可以加入$match、$project等其他管道操作,但是得注意先后顺序)
            TypedAggregation aggregation = Aggregation.newAggregation(Employee.class,
                    removeDollarOperation1, lookupOperation1,
                    unwindOperation,
                    removeDollarOperation2, lookupOperation2,
                    matchOperation);
    
            AggregationResults<Document> results = mongoTemplate.aggregate(aggregation, Document.class);
    
            System.out.println(JSONArray.toJSONString(results.getMappedResults()));
    }
    

    4、一对多:关联查询

    	/**
         * 查询部门中的所有员工,部门关联多个员工
         */
        @Test
    	public void oneToManyTableQuery() {
            // 1、展平“多”的一方
            UnwindOperation unwindOperation = new UnwindOperation(Fields.field("employeeList"));
    
            // 2、消除@DBRef引用对象中的"$id"的"$"符号
            RemoveDollarOperation removeDollarOperation1 = new RemoveDollarOperation("newEmployeeFieldName", "employeeList");
    
            // 3、使用mongodb $lookup实现左连接员工表
            LookupOperation lookupOperation1 = LookupOperation.newLookup().from("employee")
                    .localField("newEmployeeFieldName.id").foreignField("_id").as("newEmployee");
    
            // 筛选条件(非必须,看自己是否需要筛选)
            MatchOperation matchOperation = new MatchOperation(Criteria.where("newEmployee.employeeName").is("张一"));
    
            // 4、Aggregation管道操作(还可以加入$match、$project等其他管道操作,但是得注意先后顺序)
            TypedAggregation aggregation = Aggregation.newAggregation(Employee.class,
                    unwindOperation,
                    removeDollarOperation1, lookupOperation1,
                    matchOperation);
    
            AggregationResults<Document> results = mongoTemplate.aggregate(aggregation, Document.class);
    
            System.out.println(JSONArray.toJSONString(results.getMappedResults()));
        }
    

    二、讲道理

    1、自定义RemoveDollarOperation管道操作的作用

    先谈谈mongodb原生$lookup

    我们先来看下mongodb的$lookup操作,这是mongodb $lookup的原生语法

    {
       $lookup:
         {
           from: "collection to join(集合名)",
           localField: "field from the input documents(外键)",
           foreignField: "field from the documents of the "from" collection(被左连接的表的关联主键)",
           as: "output array field(存放连接获得的结果的列名)"
         }
    }
    

    然后使用原生语法进行lookup关联操作,我们来看下员工表与部门表在Mongodb中的数据

    // employee
    {
        "_id": ObjectId("5c244aafc8fbfb40c02d830c"),
        "employeeName": "张一",
        "phone": "159228359xx",
        "department": DBRef("department", ObjectId("5c244aafc8fbfb40c02d830b")),
        "_class": "com.example.mongo.domain.company.Employee"
    }
    
    // department
    {
        "_id": ObjectId("5c244aafc8fbfb40c02d830b"),
        "departmentName": "信息开发系统",
        "company": DBRef("company", ObjectId("5c244aafc8fbfb40c02d830a")),
        "employeeList": [
            DBRef("employee", ObjectId("5c244aafc8fbfb40c02d830c")),
            DBRef("employee", ObjectId("5c244aafc8fbfb40c02d830d"))
        ],
        "_class": "com.example.mongo.domain.company.Department"
    }
    
    

    你以为可以直接通过下面方式进行表连接操作吗,那就错了
    在这里插入图片描述
    执行上面的mongo语句,会报以下错误
    在这里插入图片描述
    错误原因:field的名称不支持以"$"开头

    那问题就来了,既然mongo原生lookup都不支持这一的操作,更何况Spring data mongodb了呢,那"localField"到底该填什么才能实现表关联呢?

    去掉DBRef中"$id"的"$"

    既然不能以"$“开头,那我就把”$"去掉呗:

    MongoDB官方提供的一个方法:https://jira.mongodb.org/browse/SERVER-14466

    db.collection.aggregate({$addFields:{"newFieldName":
         {$arrayToObject:{$map:{
              input:{$objectToArray:"$localFieldName"}, 
              in:{
                 k:{$cond:[ 
                         {$eq:[{"$substrCP":["$$this.k",0,1]},{$literal:"$"}]},
                         {$substrCP:["$$this.k",1,{$strLenCP:"$$this.k"}]},
                         "$$this.k"
                 ]},
                 v:"$$this.v"
               }
             }}}
    }})
    

    使用前:

    "department": DBRef("department", ObjectId("5c244aafc8fbfb40c02d830b"))
    

    使用后:

    "department": {"ref":"department", "id": "5c244aafc8fbfb40c02d830b"}
    

    去除"$“的方式是通过在结果中新追加一列"newFieldName”,这列的值是来至"$localFieldName"。

    所以我们在使用过程中只需替换上面两处的值即可。

    来,我们按这方式操作一波:(修改为"newDepartmentFieldName","$department")

    db.employee.aggregate([{
        "$addFields": {
            "newDepartmentFieldName": {
                "$arrayToObject": {
                    "$map": {
                        "input": {
                            "$objectToArray": "$department"
                        },
                        "in": {
                            "k": {
                                "$cond": [{
                                    "$eq": [{
                                        "$substrCP": ["$$this.k", 0, 1]
                                    }, {
                                        "$literal": "$"
                                    }]
                                }, {
                                    "$substrCP": ["$$this.k", 1, {
                                        "$strLenCP": "$$this.k"
                                    }]
                                }, "$$this.k"]
                            },
                            "v": "$$this.v"
                        }
                    }
                }
            }
        }
    }, {
        "$lookup": {
            "from": "department",
            "localField": "newDepartmentFieldName.id",
            "foreignField": "_id",
            "as": "newDepartment"
        }
    }])
    

    结果出来咯,老铁们

    {
        "_id": ObjectId("5c244aafc8fbfb40c02d830c"),
        "employeeName": "张一",
        "phone": "159228359xx",
        "department": DBRef("department", ObjectId("5c244aafc8fbfb40c02d830b")),
        "_class": "com.example.mongo.domain.company.Employee",
        "newDepartmentFieldName": {
            "ref": "department",
            "id": ObjectId("5c244aafc8fbfb40c02d830b")
        },
        "newDepartment": [
            {
                "_id": ObjectId("5c244aafc8fbfb40c02d830b"),
                "departmentName": "信息开发系统",
                "company": DBRef("company", ObjectId("5c244aafc8fbfb40c02d830a")),
                "employeeList": [
                    DBRef("employee", ObjectId("5c244aafc8fbfb40c02d830c")),
                    DBRef("employee", ObjectId("5c244aafc8fbfb40c02d830d"))
                ],
                "_class": "com.example.mongo.domain.company.Department"
            }
        ]
    }
    
    自定义RemoveDollarOperation管道操作

    前面说了这么多,就是想告诉你们,我为什么要自定义一个RemoveDollarOperation管道操作。就是为了解决Mongodb $lookup的"localField"的值不支持以"$"开头

    以下是RemoveDollarOperation的实现:

    只需implements AggregationOperation,实现toDocument()方法即可

    /**
     * @author : zhangmeng
     * Date : 2018/12/27 11:13
     * Description : 自定义的Spring data mongodb的Aggregation Operation
     */
    public class RemoveDollarOperation implements AggregationOperation {
        /**
         * 查询结果新追加的列名
         */
        private String newField;
    
        /**
         * 需要关联的表中的外键
         */
        private String localField;
    
        public RemoveDollarOperation(String newField, String localField) {
            this.newField = newField;
            this.localField = localField;
        }
    
        @Override
        public Document toDocument(AggregationOperationContext context) {
            List<Object> eqObjects = new ArrayList<>();
            eqObjects.add(new Document("$substrCP", Arrays.asList("$$this.k", 0, 1)));
            eqObjects.add(new Document("$literal", "$"));
    
            List<Object> substrCPObjects = new ArrayList<>();
            substrCPObjects.add("$$this.k");
            substrCPObjects.add(1);
            substrCPObjects.add(new Document("$strLenCP", "$$this.k"));
    
            List<Object> objects = new ArrayList<>();
            objects.add(new Document("$eq", eqObjects));
            objects.add(new Document("$substrCP", substrCPObjects));
            objects.add("$$this.k");
    
            Document operation = new Document(
                    "$addFields",
                    new Document(newField,
                            new Document("$arrayToObject",
                                    new Document("$map",
                                            new Document("input",new Document("$objectToArray", "$"+localField))
                                                    .append("in", new Document("k",new Document("$cond", objects))
                                                            .append("v", "$$this.v")))
                            )
                    )
            );
    
            return context.getMappedObject(operation);
        }
    }
    

    你看到那么多的Document 拼接,其实就是为了实现

    db.collection.aggregate({$addFields:{"newFieldName":
         {$arrayToObject:{$map:{
              input:{$objectToArray:"$localFieldName"},  ...
    

    注意事项:
    在实现过程中,可能因为Spring-data-mongodb版本不同,

    	
    	// Spring-data-mongodb 2.0以上使用Org.bson的Document (具体版本不确定)
    
    	@Override
        public Document toDocument(AggregationOperationContext context) {
        	...
        	...
    		Document operation = new Document(
                    "$addFields",
                    new Document(newField,"")
                    ...
                    ...
            );
    
            return context.getMappedObject(operation);
    	}
    
    	// Spring-data-mongodb 2.0以下使用com.mongodb.BasicDBObject
    	
    	@Override
        public DBObject toDBObject(AggregationOperationContext context) {
    		...
        	...
    		DBObject operation = new DBObject (
                    "$addFields",
                    new DBObject (newField,"")
                    ...
                    ...
            );
    
            return context.getMappedObject(operation);
    }
    

    2、实例中的一对一多表关联查询中的第4步使用UnwindOperation的原因

    可能当我们实现了实例1中的一对一两表关联查询后,顺理成章就觉得如果要再关联第三张表的话,直接再使用

    一次RemoveDollarOperation,LookupOperation进行关联

    db.employee.aggregate([{
        "$addFields": {
            "newDepartmentFieldName": {
                "$arrayToObject": {
                    "$map": {
                        "input": {
                            "$objectToArray": "$department"
                        },
                        "in": {
                            "k": {
                                "$cond": [{
                                    "$eq": [{
                                        "$substrCP": ["$$this.k", 0, 1]
                                    }, {
                                        "$literal": "$"
                                    }]
                                }, {
                                    "$substrCP": ["$$this.k", 1, {
                                        "$strLenCP": "$$this.k"
                                    }]
                                }, "$$this.k"]
                            },
                            "v": "$$this.v"
                        }
                    }
                }
            }
        }
    }, {
        "$lookup": {
            "from": "department",
            "localField": "newDepartmentFieldName.id",
            "foreignField": "_id",
            "as": "newDepartment"
        }
    }, {
        "$addFields": {
            "newCompanyFieldName": {
                "$arrayToObject": {
                    "$map": {
                        "input": {
                            "$objectToArray": "$newDepartment.company"
                        },
                        "in": {
                            "k": {
                                "$cond": [{
                                    "$eq": [{
                                        "$substrCP": ["$$this.k", 0, 1]
                                    }, {
                                        "$literal": "$"
                                    }]
                                }, {
                                    "$substrCP": ["$$this.k", 1, {
                                        "$strLenCP": "$$this.k"
                                    }]
                                }, "$$this.k"]
                            },
                            "v": "$$this.v"
                        }
                    }
                }
            }
        }
    }, {
        "$lookup": {
            "from": "company",
            "localField": "newCompanyFieldName.id",
            "foreignField": "_id",
            "as": "newCompany"
        }
    }])
    

    但是,执行后就错了:
    在这里插入图片描述

    来来来,我们一步一步分析下

    这是Employee关联Department后,得到的结果,“newDepartment"是关联后得到的结果:
    在这里插入图片描述
    我们如果要进一步Department关联Company的话,直接再使用RemoveDollarOperation,LookupOperation是不行的,因为在消除”$"操作时入参需要一个非数组对象,而前一步的结果的"newDepartment"是一个数组,所以报错了
    在这里插入图片描述

    为了得到一个非数组对象,我们就要使用$unwind将"newDepartment"展平
    在这里插入图片描述

    然后就可以使用"newDepartment"继续RemoveDollarOperation,LookupOperation操作了。最终得到Employee关

    联Department关联Company的结果了。如果还想继续关联,就以此类推。

    最终得出的模型:
    
    一对一两表关联的步骤:
    1、RemoveDollarOperation
    2、LookupOperation
    
    一对一多表关联的步骤:
    1、RemoveDollarOperation  2、LookupOperation
    3、UnwindOperation
    4、RemoveDollarOperation  5、LookupOperation
    ...
    
    一对多表关联的步骤:
    1、UnwindOperation
    2、RemoveDollarOperation
    3、LookupOperation
    
    展开全文
  • 数据库之多表联合查询

    千次阅读 2020-04-24 00:35:48
    多表联合查询(一对数据显示、数据展示) 二、知识点业务场景 一对多关联: 学生和成绩的关系 用户与订单的关系 企业与员工的关系 用户与银行卡的关系 多关联: 学生和选课的关系 订单和...
  • sqlserver 多表联合查询

    万次阅读 2019-04-03 16:53:16
    数据库查询时,对单的查询很难满足需求,通常都需要多表联合查询多表连接大致分为内连接和外连接。 内连接和外连接的区别主要体现在返回数据上,内连接返回的是符合连接条件和查询条件的记录,外连接返回的...
  • MyBatisPlus多表关联查询,返回list

    千次阅读 2020-11-16 15:19:16
    菜单和角色是关系,有一个关联表,菜单去重,角色返回集合 public class MenuVO extends SysMenu { private List<SysRole> roles; } 实现一 @Select("select rm.menu_id,m.`name`,m.url from ...
  • MySQL多表关联查询优化

    千次阅读 2019-11-28 10:37:20
    最近在对运营报表导出进行优化,总结了一些多表关联查询优化的点记录一下。 避免临时表 通过 Explain 分析 SQL 语句,尽量不要使用到临时表。GROUP BY (Explain具体详解,可以看这篇博客) 最容易造成使用临时表,...
  • 摘要:C#源码,数据库应用,多表查询 多表联合查询的C#程序,和源代码,截图没有显示出数据,因测试时候SQL坏掉了,一时搞不定了,呵呵,凑合看吧,感兴趣的就自己下载源码,重新编译吧,分享给C#新手的。
  • Mybatis注解实现多表关联查询

    千次阅读 2020-03-16 21:38:45
    目录2020.3.16Mybatis注解实现多表关联查询1、Demo描述1)功能描述:2)E-R图:2、Entity类3、数据库表设计1)student表2)question表3)doctor表4)中间表及其外键约束4、方法实现0)备注:1)Mapper中的方法及其...
  • MongoDB之多表关联查询

    千次阅读 2020-08-15 10:17:22
    最近在看同事代码的时候,注意到了$lookup多表关联查询,不太清楚类比MySQL中是哪种连接查询,因此就有了此次的测试总结。接下来,我会用测试结果来介绍MySQL中的内连接、左外连接、右外连接,介绍MongoDB中$lookup...
  • 最近在做项目的时候遇到了一对的结构数据存储问题。由于前面的是使用的greendao框架,所以就研究了一下这方面的资料。但是网上的都是官网的一些资料。下面我就简单的介绍一下如何使用。由于是demo很简单所以也不放...
  • 给坛友演示WinForm+SQL多表联合自定义查询,SQL结构见: http://bbs.csdn.net/topics/392297046
  • mongodb 多表联合查询

    千次阅读 2020-11-26 18:41:59
    参考资料: 详解MongoDB中的多表关联查询($lookup) https://www.cnblogs.com/xuliuzai/p/10055535.html mongodb表联查 https://blog.csdn.net/eric_to/article/details/90093806 $lookup使用 ...
  • 多表关联查询数量

    2020-12-17 17:08:46
    //多表关联查询数量 select user, t1.count1, t2.count2 from user t left join ( select user_id, count(sport_type) as count1 from sport group by user_id ) t1 on t.id = t1.user_id left join ( select user_...
  • mysql,多表联接查询练习,mysql,多表联接内联,外联练习。 mysql,多表联接查询练习,mysql,多表联接内联,外联练习。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 515,249
精华内容 206,099
关键字:

多表关联查询