• 使用in作为查询条件优化SQL并使用set筛选结果集


    一次SQL优化

    SQL语句为:

     根据tenantId、skuNo、ownerNo批量查询商品属性
        <select id="queryBatchSkuStoreAttrs" parameterType="java.util.List"
                resultMap="BaseResultMap">
            <foreach collection="list" item="item" index="index" separator=" union ">
                SELECT
    
                *****
    
                FROM  ssa JOIN
                ssi
                ON #####
                AND #####
                AND ###
                WHERE ssa.xxx = #{item.xxx,jdbcType=VARCHAR} AND ssa.yyy = #{item.yyy,jdbcType=VARCHAR}
                AND ssa.zzz = #{item.zzz,jdbcType=VARCHAR}
            </foreach>
        </select>
    

    很明显该SQL存在大量拼接重复语句的问题,在一个大循环中重复调用造成性能消耗。而且随着List的增大,生成的SQL语句也会非常冗长。

    优化方式: 将原SQL改为in条件查询,减少查询次数。
    修改后的SQL为:

        <select id="queryBatchSkuStoreAttrs" parameterType="java.util.List" resultMap="BaseResultMap">
            SELECT
    
            *****
    
            FROM  ssa JOIN
            ssi
            ON #####
            AND #####
            AND ###
            WHERE ssa.xxx IN
                (<foreach collection="list" item="item" index="index" separator=",">
                    #{item.xxx,jdbcType=VARCHAR}
                </foreach>)
            AND ssa.yyy IN
                (<foreach collection="list" item="item" index="index" separator=",">
                    #{item.yyy,jdbcType=VARCHAR}
                </foreach>)
            AND ssa.zzz IN
                (<foreach collection="list" item="item" index="index" separator=",">
                    #{item.zzz,jdbcType=VARCHAR}
                </foreach> )
        </select>
    
    

    但是这样得到的结果是以查询条件的笛卡尔积而生成的,其中必然包含不属于原查询条件的结果,因此需要对得到的结果集进行去重处理,得到与原结果集相匹配的结果集和。

    众所周知,set具有无序、不重复 的特点。因此,可以利用这个特点对结果集List中的元素与查询条件集做对比进行筛选,若结果集的字段能插入查询条件集生成的set中,说明该条记录与原查询条件不匹配,也就是需要删除的记录。示例代码如下:

        List<SkuStoreAttr> skuStoreAttrsNew = skuStoreAttrDao.queryBatchSkuStoreAttrs(store);
    	//使用set去除多余的信息
        Set<String> keySet = new HashSet<>();
    	store.forEach(skuStoreAttr -> keySet.add(makeKey(skuStoreAttr)));
    	for(Iterator<SkuStoreAttr> iterator = skuStoreAttrsNew.iterator();iterator.hasNext();){
    		String key = makeKey(iterator.next());
    		if(keySet.add(key)){
    			iterator.remove();
    		}
    	}
    

    其中,makeKey()方法提取dto中的特征字段作为每个元素的唯一标识,用来标记每一个dto
    在删除重复元素时,使用迭代器Iterator进行遍历处理,保证List中的元素可以被正确的删除。遍历之后便可以得到无重复的List。

  • 相关阅读:
    前端工程师必备:前端的模块化
    1414. 和为 K 的最少斐波那契数字数目(贪心)
    62. 不同路径(经典dp问题简单路径)
    1051. 高度检查器(排序比较)
    1144. 递减元素使数组呈锯齿状(两次扫)
    面试题 16.04. 井字游戏(模拟即可)
    微信小程序 base64ToArrayBuffer
    人人商城手机端添加控制器
    微擎自定义回复规则
    JS 对浏览器相关的操作
  • 原文地址:https://www.cnblogs.com/liesun/p/11696078.html
Copyright © 2020-2023  润新知