mysatis中子查询剖析

mybatis中查询代码是这样写的

 <resultMap id="riskDTOMap" type="vip.xiaonuo.modular.safety.risk.common.entity.dto.SafetyAllRiskListDTO">
       <result column="id" property="id"></result>
       <result column="org_id" property="orgId"></result>
       <result column="inspect_type" property="inspectType"></result>
       <result column="risk_level" property="riskLevel"></result>
       <result column="responsible_user" property="responsibleUser"></result>
       <result column="risk_descript" property="riskDescript"></result>
       <result column="risk_photo" property="riskPhoto"></result>
       <result column="risk_status" property="riskStatus"></result>
       <result column="create_time" property="createTime"></result>
       <result column="create_user" property="createUser"></result>
       <result column="rectification_time" property="rectificationTime"></result>
       <result column="orgName" property="orgName"></result>
       <result column="responsibleUserName" property="responsibleUserName"></result>
       <result column="createUserName" property="createUserName"></result>
       <result column="risk_name" property="riskName"></result>
       <result column="risk_name_id" property="riskNameId"></result>
        <collection property="recordListDTOS"
                    ofType="vip.xiaonuo.modular.safety.risk.common.entity.dto.SafetyAllRiskRecordListDTO"
                    select="selectRecordDTOs"
                    column="{riskId=id}"/>
    </resultMap>
    
 <select id="selectAllRiskList" resultMap="riskDTOMap">
        SELECT
        risk.id, risk.org_id,risk.inspect_type,risk.risk_level,risk.responsible_user,risk.risk_descript,risk.risk_photo,
        risk.risk_status,risk.create_time,risk.create_user,risk.rectification_time,rname.risk_name,rname.id risk_name_id,
        org.`name` orgName,U1.name responsibleUserName,U2.name createUserName
        FROM
        `safety_risk` risk
        LEFT JOIN
        sys_org org on  risk.org_id = org.id
        LEFT JOIN
        sys_user U1 on U1.id = risk.responsible_user
        LEFT JOIN
        sys_user U2 on U2.id = risk.create_user
        LEFT JOIN
        safety_risk_name rname on risk.risk_name_id = rname.id
        <where>
            <if test="null != riskParam.createUserName and riskParam.createUserName != ''">
                and u2.name like concat('%',#{riskParam.createUserName},'%')
            </if>
            <if test="null != riskParam.riskLevel">
                and risk_level = #{riskParam.riskLevel}
            </if>
            <if test="null != riskParam.riskName and ''!= riskParam.riskName">
                and rname.id =  #{riskParam.riskName}
            </if>
            <if test="null != riskParam.riskStatus">
                and risk_status = #{riskParam.riskStatus}
            </if>
            <if test="null != riskParam.inspectType">
                and inspect_type = #{riskParam.inspectType}
            </if>
            <if test="null != riskParam.orgIds and riskParam.orgIds.size > 0">
                and org_id in
                <foreach collection="riskParam.orgIds" item="e" open="(" close=")" separator=",">
                    #{e}
                </foreach>
            </if>
            <if test="null != riskParam.riskStatues and riskParam.riskStatues.size > 0">
                and risk_status in
                <foreach collection="riskParam.riskStatues" item="e" open="(" close=")" separator=",">
                    #{e}
                </foreach>
            </if>
            <if test="null != riskParam.id">
                and risk.id = #{riskParam.id}
            </if>
            <if test="null != riskParam.ids and riskParam.ids.size > 0">
                and risk.id in
                <foreach collection="riskParam.ids" item="e" open="(" close=")" separator=",">
                    #{e}
                </foreach>
            </if>
            <if test="null != riskParam.createUser">
                and risk.create_user = #{riskParam.createUser}
            </if>
            <if test="null != riskParam.responsibleUser ">
                and risk.responsible_user = #{riskParam.responsibleUser}
            </if>
            <if test="null != riskParam.checkTimeStart and riskParam.checkTimeStart != ''">
                and risk.create_time &gt;= #{riskParam.checkTimeStart}
            </if>
            <if test="null != riskParam.checkTimeEnd and riskParam.checkTimeEnd != ''">
                and risk.create_time &lt;= #{riskParam.checkTimeEnd}
            </if>
            <if test="null != riskParam.rectificationTimeStart and riskParam.rectificationTimeStart != ''">
                and rectification_time &gt;= #{riskParam.rectificationTimeStart}
            </if>
            <if test="null != riskParam.rectificationTimeEnd and riskParam.rectificationTimeEnd != ''">
                and rectification_time &lt;= #{riskParam.rectificationTimeEnd}
            </if>
        </where>
        order by
        risk.create_time desc
    </select>
    
 <select id="selectRecordDTOs" resultType="vip.xiaonuo.modular.safety.risk.common.entity.dto.SafetyAllRiskRecordListDTO">
        SELECT
                safety_risk_record.id recordId,
                risk_id,
                rectification_measure,
                rectification_photo,
                check_status,
                check_descript,
                completion_time,
                delay_day,
                delay_status,
                delay_remark,
                safety_risk_record.create_time recordCreateTime,
                safety_risk_record.create_user,
                safety_risk_record.update_time,
                safety_risk_record.update_user,
                F1.file_object_name rectificationPhotoPath
        from
            safety_risk_record
        LEFT JOIN
            sys_file_info F1 on F1.id = safety_risk_record.rectification_photo
        where
            risk_id = #{riskId}
    </select>

返回实体类

/*
Copyright [2020] [https://www.xiaonuo.vip]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:

1.请不要删除和修改根目录下的LICENSE文件。
2.请不要删除和修改Snowy源码头部的版权声明。
3.请保留源码和相关描述文件的项目出处,作者声明等。
4.分发源码时候,请注明软件出处 https://gitee.com/xiaonuobase/snowy
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/xiaonuobase/snowy
6.若您的项目无法满足以上几点,可申请商业授权,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.modular.safety.risk.common.entity.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 隐患整改
 *
 * @author Eternal
 * @date 2022-09-27 09:21:16
 */
@Data
public class SafetyAllRiskListDTO {
    /**
     * 主键
     */
    private Long id;

    /**
     * 组织机构ID
     */
    private Long orgId;

    /**
     * 组织机构名称
     */
    private String orgName;

    /**
     * 隐患名称
     */
    private String riskName;

    private Long riskNameId;
    /**
     * 检查类型
     */
    private Integer inspectType;

    /**
     * 隐患级别
     */
    private Integer riskLevel;

    /**
     * 整改责任人id
     */
    private Long responsibleUser;

    /**
     * 整改责任人
     */
    private String  responsibleUserName;

    /**
     * 整改责任人Account
     */
    private String responsibleAccount;

    /**
     * 整改期限
     */
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date rectificationTime;

    /**
     * 隐患描述
     */
    private String riskDescript;

    /**
     * 隐患照片
     */
    private String riskPhoto;

    /**
     * 整改核查id
     */
    private Long recordId;

    /**
     * 隐患状态
     */
    private Integer riskStatus;

    /**
     * 检查人姓名
     */
    private String createUserName;

    /**
     * 创建时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date createTime;

    /**
     * 创建人
     */
    private Long createUser;

    /**
     * 更新时间
     */
    private Date updateTime;

    /**
     * 更新人
     */
    private Long updateUser;

    /**
     * 整改核查列表信息
     */
    private List<SafetyAllRiskRecordListDTO> recordListDTOS;

}


先说结论

再mybatis中这样写子查询,和在循环中写select通过外键查询效果是一样的,效率很低,速度很慢。
通过测试,他有一个懒加载的机制
再例子中:只有用到了recordListDTOS 才会执行子查询

在这里插入图片描述
可以看到,这条sql的执行时间不到1s,打印的sql日志也只有主体sql
但是当循环取recordListDTOS时:
在这里插入图片描述打印了一千多条sql进行外键查询,耗时17s

真是坑爹啊▄█▀█●

### SQL Server 中子查询的使用方法与示例 #### 子查询概述 子查询是在另一个 `SELECT`、`INSERT`、`UPDATE` 或 `DELETE` 语句内部执行的查询。这种结构允许更灵活的数据检索方式,尤其是在处理多表关联的情况下[^2]。 #### 使用等于运算符 (`=`) 的子查询 当需要匹配单个值时,可以使用等号运算符。例如,在两个表格之间基于某一字段相等关系获取特定记录: ```sql SELECT column1 FROM table1 WHERE column1 = (SELECT column2 FROM table2 WHERE condition); ``` 此命令会先执行括号内的子查询部分,得到唯一的结果并与外部查询条件对比,从而筛选符合条件的数据行[^1]。 #### IN 运算符的应用场景 如果希望从一组可能的值中挑选,则可采用 `IN` 关键字配合子查询实现这一目标。比如寻找属于某几个分类的商品列表: ```sql SELECT ProductID,ProductName FROM Products WHERE CategoryID IN ( SELECT DISTINCT CategoryID FROM Categories WHERE CategoryName LIKE 'Beverages%' ); ``` 这段代码表示选取那些类别名称以 "Beverages" 开头的产品信息[^4]。 #### ANY/SOME 及 ALL 运算符详解 对于涉及范围判断的操作,如大于最小值小于最大值等情况,可以通过 `ANY`/`SOME` 和 `ALL` 来简化逻辑表达。考虑如下情况——找出价格高于任意一款饮料类产品的商品: ```sql SELECT p.ProductName,p.UnitPrice FROM Products AS p WHERE UnitPrice > ANY( SELECT UnitPrice FROM Products WHERE CategoryID = 1 /*假设 Beverages 类别的 ID 是 1 */ ); ``` 这里利用了 `ANY` 关键词使得只要有一个满足即可成立;而如果是要求全部都超过的话则应该替换为 `ALL`。 #### 实际应用案例展示 为了更好地理解这些概念的实际用途,下面给出一个具体的例子:统计各城市客户订单数量最多的前两名供应商及其供应次数。 ```sql WITH TopSuppliersPerCity AS ( SELECT c.City, s.CompanyName Supplier, COUNT(o.OrderID) OrderCount, RANK() OVER(PARTITION BY c.City ORDER BY COUNT(o.OrderID) DESC) RankNum FROM Customers c JOIN Orders o ON c.CustomerID = o.CustomerID JOIN [Order Details] od ON o.OrderID = od.OrderID JOIN Products p ON od.ProductID = p.ProductID JOIN Suppliers s ON p.SupplierID = s.SupplierID GROUP BY c.City, s.CompanyName ) SELECT City,Supplier,OrderCount FROM TopSuppliersPerCity tspc WHERE RankNum <= 2; ``` 上述脚本通过窗口函数 `RANK()` 计算了每座城市的顶级供货商排名,并最终限定了只取前两位作为输出结果[^5]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值