You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
//1、 条件值处理跟具体sql分离
//2、 将条件值前置通过filters 定义的通用方法加工规整(大多数是不需要额外处理的)
<sqlid="show_case">
<filters>
<!-- 参数statusAry只要包含-1(代表全部)则将statusAry设置为null不参与条件检索 -->
<eqparams="statusAry"value="-1" />
</filters>
<value><![CDATA[ select * from sqltoy_device_order_info t where #[t.status in (:statusAry)] #[and t.ORDER_ID=:orderId] #[and t.ORGAN_ID in (:authedOrganIds)] #[and t.STAFF_ID in (:staffIds)] #[and t.TRANS_DATE>=:beginAndEndDate[0]] #[and t.TRANS_DATE<:beginAndEndDate[1]] ]]>
</value>
</sql>
mybatis同样的功能的写法
<selectid="show_case"resultMap="BaseResultMap">
select *
from sqltoy_device_order_info t
<where>
<iftest="statusAry!=null">
and t.status in
<foreachcollection="status"item="statusAry"separator=","open="("close=")">
#{status}
</foreach>
</if>
<iftest="orderId!=null">
and t.ORDER_ID=#{orderId}
</if>
<iftest="authedOrganIds!=null">
and t.ORGAN_ID in
<foreachcollection="authedOrganIds"item="order_id"separator=","open="("close=")">
#{order_id}
</foreach>
</if>
<iftest="staffIds!=null">
and t.STAFF_ID in
<foreachcollection="staffIds"item="staff_id"separator=","open="("close=")">
#{staff_id}
</foreach>
</if>
<iftest="beginDate!=null">
and t.TRANS_DATE>=#{beginDate}
</if>
<iftest="endDate!=null">
and t.TRANS_DATE<#{endDate}
</if>
</where>
</select>
2.3 天然防止sql注入,执行过程:
假设sql语句如下
select *
from sqltoy_device_order_info t
where #[t.ORGAN_ID in (:authedOrganIds)]
#[and t.TRANS_DATE>=:beginDate]
#[and t.TRANS_DATE<:endDate]
java调用过程:
lightDao.find(sql, MapKit.keys("authedOrganIds","beginDate", "endDate").values(authedOrganIdAry,beginDate,null), DeviceOrderInfoVO.class);
最终执行的sql是这样的:
select *
from sqltoy_device_order_info t
where t.ORDER_ID=?
and t.ORGAN_ID in (?,?,?)
and t.TRANS_DATE>=?
然后通过: pst.set(index,value) 设置条件值,不存在将条件直接作为字符串拼接为sql的一部分
5、在极特殊情况下sqltoy分页考虑是最优化的,如:with t1 as (),t2 as @fast(select * from table1) select * from xxx
这种复杂查询的分页的处理,sqltoy的count查询会是:with t1 as () select count(1) from table1,
如果是:with t1 as @fast(select * from table1) select * from t1 ,count sql 就是:select count(1) from table1
2.4.2 分页sql示例
<!-- 快速分页和分页优化演示 -->
<sqlid="sqltoy_fastPage">
<!-- 分页优化器,通过缓存实现查询条件一致的情况下在一定时间周期内缓存总记录数量,从而无需每次查询总记录数量 --><!-- parallel:是否并行查询总记录数和单页数据,当alive-max=1 时关闭缓存优化 --><!-- alive-max:最大存放多少个不同查询条件的总记录量; alive-seconds:查询条件记录量存活时长(比如120秒,超过阀值则重新查询) -->
<page-optimizeparallel="true"alive-max="100"alive-seconds="120" />
<value><![CDATA[ select t1.*,t2.ORGAN_NAME -- @fast() 实现先分页取10条(具体数量由pageSize确定),然后再关联 from @fast(select t.* from sqltoy_staff_info t where t.STATUS=1 #[and t.STAFF_NAME like :staffName] order by t.ENTRY_DATE desc ) t1 left join sqltoy_organ_info t2 on t1.organ_id=t2.ORGAN_ID]]>
</value>
<!-- 这里为极特殊情况下提供了自定义count-sql来实现极致性能优化 --><!-- <count-sql></count-sql> -->
</sql>
<sqlid="sqltoy_showcase">
<value>
<![CDATA[ select * from sqltoy_user_log t where t.user_id=:userId ]]>
</value>
</sql>
<!-- sqlId_数据库方言(小写) -->
<sqlid="sqltoy_showcase_mysql">
<value>
<![CDATA[ select * from sqltoy_user_log t where t.user_id=:userId ]]>
</value>
</sql>
2.8 提供行列转换、分组汇总、同比环比、树排序汇总等
水果销售记录表
品类
销售月份
销售笔数
销售数量(吨)
销售金额(万元)
苹果
2019年5月
12
2000
2400
苹果
2019年4月
11
1900
2600
苹果
2019年3月
13
2000
2500
香蕉
2019年5月
10
2000
2000
香蕉
2019年4月
12
2400
2700
香蕉
2019年3月
13
2300
2700
2.8.1 行转列(列转行也支持)
<!-- 行转列 -->
<sqlid="pivot_case">
<value>
<![CDATA[ select t.fruit_name,t.order_month,t.sale_count,t.sale_quantity,t.total_amt from sqltoy_fruit_order t order by t.fruit_name ,t.order_month]]>
</value>
<!-- 行转列,将order_month作为分类横向标题,从sale_count列到total_amt 三个指标旋转成行 -->
<pivotstart-column="sale_count"end-column="total_amt" group-columns="fruit_name"category-columns="order_month" />
</sql>
效果
品类
2019年3月
2019年4月
2019年5月
笔数
数量
总金额
笔数
数量
总金额
笔数
数量
总金额
香蕉
13
2300
2700
12
2400
2700
10
2000
2000
苹果
13
2000
2500
11
1900
2600
12
2000
2400
2.8.2 分组汇总、求平均(可任意层级)
<sqlid="group_summary_case">
<value>
<![CDATA[ select t.fruit_name,t.order_month,t.sale_count,t.sale_quantity,t.total_amt from sqltoy_fruit_order t order by t.fruit_name ,t.order_month]]>
</value>
<!-- reverse 是否反向 -->
<summarycolumns="sale_count,sale_quantity,total_amt"reverse="true">
<!-- 层级顺序保持从高到低 -->
<globalsum-label="总计"label-column="fruit_name" />
<!-- order-column: 分组排序列(对同分组进行排序),order-with-sum:默认为true,order-way:desc/asc -->
<groupgroup-column="fruit_name"sum-label="小计"label-column="fruit_name" />
</summary>
</sql>
效果
品类
销售月份
销售笔数
销售数量(吨)
销售金额(万元)
总计
71
12600
14900
小计
36
5900
7500
苹果
2019年5月
12
2000
2400
苹果
2019年4月
11
1900
2600
苹果
2019年3月
13
2000
2500
小计
35
6700
7400
香蕉
2019年5月
10
2000
2000
香蕉
2019年4月
12
2400
2700
香蕉
2019年3月
13
2300
2700
2.8.3 先行转列再环比计算
<!-- 列与列环比演示 -->
<sqlid="cols_relative_case">
<value>
<![CDATA[ select t.fruit_name,t.order_month,t.sale_count,t.sale_amt,t.total_amt from sqltoy_fruit_order t order by t.fruit_name ,t.order_month]]>
</value>
<!-- 数据旋转,行转列,将order_month 按列显示,每个月份下面有三个指标 -->
<pivotstart-column="sale_count"end-column="total_amt" group-columns="fruit_name"category-columns="order_month" />
<!-- 列与列之间进行环比计算 -->
<cols-chain-relativegroup-size="3"relative-indexs="1,2"start-column="1"format="#.00%" />
</sql>