mybatis sql 的一些问题 with。。。as。。。



<select id="selectIntegral" resultMap="IntraMap"
parameterType="com.sgcc.procurement.main.entity.integral.IntegralBean">
WITH TEMP AS
(SELECT C.BP_RULE_FLOW_ID, MAX(C.OPERATE_TIME)
OPERATE_TIME
FROM EC_BP_EXCHANGELOG C
GROUP BY C.BP_RULE_FLOW_ID)
SELECT
A.BP_RULE_FLOW_ID,
A.CORPORATION_ID,
A.APPLICATION_NO,
A.SCALE_MALL,
A.SCALE_PALTFORM,
A.TIME_BEGIN,
A.TIME_END,
<!-- TO_CHAR(A.TIME_BEGIN,'yyyy-mm-dd hh24:mi:ss') as TIME_BEGIN, -->
<!-- TO_CHAR(A.TIME_END,'yyyy-mm-dd hh24:mi:ss') as TIME_END, -->
A.RULE_STATUS,
B.ID,
B.OPERATIOR_TYPE,
B.OPERATIOR,
B.OPERATIOR_NAME,
B.OPERATE_TIME,
<!-- TO_CHAR(B.OPERATE_TIME,'yyyy-mm-dd hh24:mi:ss') as OPERATE_TIME, -->
B.OPERATE_DESC,
B.APPROVE_REMARK
FROM EC_BP_EXCHANGE A,
EC_BP_EXCHANGELOG B, TEMP
WHERE A.BP_RULE_FLOW_ID = B.BP_RULE_FLOW_ID
AND B.BP_RULE_FLOW_ID = TEMP.BP_RULE_FLOW_ID
AND B.OPERATE_TIME =
TEMP.OPERATE_TIME
and A.RULE_STATUS = B.RULE_STATUS
<if test="bpRuleFlowId != null and bpRuleFlowId != ''">
and A.BP_RULE_FLOW_ID =#{bpRuleFlowId,jdbcType=VARCHAR}
</if>
<if test="corporationId != null and corporationId != ''">
and A.CORPORATION_ID= #{corporationId,jdbcType=VARCHAR}
</if>
<if test="applicationNo != null and applicationNo != ''">
and A.APPLICATION_NO= #{applicationNo,jdbcType=VARCHAR}
</if>
<if test="ruleStatus != null and ruleStatus != ''">
and A.RULE_STATUS= #{ruleStatus,jdbcType=VARCHAR}
</if>
<if test="(timeEnd == null or timeEnd == '') and (timeBegin != null and timeBegin != '')">
<![CDATA[
and a.TIME_BEGIN <= #{timeBegin,jdbcType=VARCHAR}
 and  a.TIME_END >= #{timeBegin,jdbcType=VARCHAR} ]]>

</if>
<if test="(timeBegin == null or timeBegin == '') and (timeEnd != null and timeEnd != '')">
<![CDATA[  and a.TIME_BEGIN <= #{timeEnd,jdbcType=VARCHAR}
    and a.TIME_END >= #{timeEnd,jdbcType=VARCHAR} ]]>
</if>
<if test="timeBegin != null and timeBegin != ''and timeEnd != null and timeEnd != ''">
<![CDATA[and ( 
   (a.TIME_BEGIN >= #{timeBegin,jdbcType=VARCHAR} AND a.TIME_BEGIN <= #{timeEnd,jdbcType=VARCHAR} ) OR  
        (a.TIME_BEGIN <= #{timeBegin,jdbcType=VARCHAR} AND a.TIME_END >= #{timeEnd,jdbcType=VARCHAR}) OR  
        (a.TIME_END >= #{timeBegin,jdbcType=VARCHAR} and a.TIME_END <=  #{timeEnd,jdbcType=VARCHAR}) OR 
        (a.TIME_BEGIN >= #{timeBegin,jdbcType=VARCHAR} and a.TIME_END <=  #{timeEnd,jdbcType=VARCHAR})
         )  ]]>
</if>
</select>




这条sql 用到非空条件判断,  <if test="timeBegin != null and timeBegin != ''and timeEnd != null and timeEnd != ''">    
查询头用到  with as  :
3.1 with基础



使用WITH AS 语句可以为一个子查询语句块定义一个名称,使用这个子查询名称可以在查询语句的很多地方引用这个子查询。Oracle 数据库像对待内联视图或临时表一样对待被引用的子查询名称,从而起到一定的优化作用。with子句是9i新增语法。


你可以在任何一个顶层的SELECT 语句以及几乎所有类型的子查询语句前,使用子查询定义子句。被定义的子查询名称可以在主查询语句以及所有的子查询语句中引用,但未定义前不能引用。


with子句中不能嵌套定义<也就是with子句中不能有with子句>,但子查询中出现的子查询定义语句可以引用已定义的子查询名称。<可以引用前面已经定义的with子句>


with子句相关总结:





1.使用with子句可以让子查询重用相同的with查询块,通过select调用(with子句只能被select查询块引用),一般在with查询用到多次情况下。在引用的select语句之前定义,同级只能定义with关键字只能使用一次,多个用逗号分割。


2.with子句的返回结果存到用户的临时表空间中,只做一次查询,反复使用,提高效率。


3.在同级select前有多个查询定义的时候,第1个用with,后面的不用with,并且用逗号隔开。


5.最后一个with 子句与下面的查询之间不能有逗号,只通过右括号分割,with 子句的查询必须用括号括起来


6.如果定义了with子句,而在查询中不使用,那么会报ora-32035 错误:未引用在with子句中定义的查询名。(至少一个with查询的name未被引用,解决方法是移除未被引用的with查询),注意:只要后面有引用 的就可以,不一定非要在主查询中引用,比如后面的with查询也引用了,也是可以的。


7.前面的with子句定义的查询在后面的with子句中可以使用。但是一个with子句内部不能嵌套with子句。


8.当一个查询块名字和一个表名或其他的对象相同时,解析器从内向外搜索,优先使用子查询块名字。


9.with查询的结果列有别名,引用的时候必须使用别名或*。


with子句优点:





1. SQL可读性增强。比如对于特定with子查询取个有意义的名字等。


2. with子查询只执行一次,将结果存储在用户临时表空间中,可以引用多次,增强性能。


with子句语法:


With alias_name as (select1), --as和select中的括号都不能省略


alias_name2 as (select2),--后面的没有with,逗号分割,同一个主查询同级别地方,with子查询只能定义一次




alias_namen as (select n) –与下面的实际查询之间没有逗号


Select ….


with使用例子:


1.一般使用方式





如查询销售部门员工的姓名:


--with clause


with a as


(select id from s_dept where name=Sales order by id)


select last_name,title


from s_emp where dept_id in (select * from a);--使用select查询别名


使用with 子句,可以在复杂的查询中预先定义好一个结果集,然后在查询中反复使用,不使用会报错。而且with 子句获得的是一个临时表,如果在查询中使用,必须采用select from with 查询名,比如


With cnt as(select count(*) from table)


Select cnt+1 from dual;


是错误的。必须是


With cnt as(select count(*) shumu from user_tables)


Select shumu+1 from cnt;


2.在大多数子查询中引用,同级可见





再如下面两个语句含义等价:


with a as (select trade_id,name from product) --使用之前定义


select name from a where a.trade_id in (


with b as (select id from trademark where id=1) --使用之前定义


select id from b


);


select name from product where trade_id in (select id from trademark where id=1);


3. with子查询不可嵌套定义,但是后面的with定义可以引用前面的结果集。





with select_trade as (select trade_id from product where id=1),


--后面的with子查询可以引用前面的结果


select_trademark as (select name from trademark where id=(select trade_id from select_trade))


select * from select_trademark;


--这条语句错误


with select_trade as


--with中有嵌套with,不允许


( with temp as ( select trade_id from product where id=1)


select trade_id from temp


),


select_trademark as (select name from trademark where id=(select trade_id from select_trade))


select * from select_trademark;


4. 同级定义,只能有一个with





with a as (select trade_id from product),


b as (select id from trademark where rownum<3) --第2个定义不用with


select trade_id from a


minus


select id from b;


5. 在大多数子查询中定义和使用,一个复杂的例子





SELECT a ,b


FROM (


--第1个定义t_with


WITH


t_with AS (SELECT 1 a FROM DUAL)


--子查询使用t_with


SELECT x.a ,(


--内部定义了个t_with_z,并且使用t_with


WITH t_with_z as (SELECT 1 a FROM t_with )


SELECT s_1.a FROM t_with_z s_1 ,t_with s_2


6. 集合中使用with子查询





--这个是错误的,同级只能有一个with定义,当然两个可以写在一起。


SELECT *


FROM (


WITH


t_with_1 AS (SELECT 1 a ,1 b FROM DUAL)


--此后的整个语句被认为是一个主查询语句


SELECT x.a , x.b FROM t_with_1 x


union all


WITH -- 此处再次出现定义


t_with_2 AS (SELECT 1 a ,2 b FROM DUAL)


SELECT y.a ,y.b FROM t_with_2 y


--正确


SELECT *


FROM (


--第1个with


WITH


t_with_1 AS (SELECT 1 a ,1 b FROM DUAL)


SELECT x.a , x.b ,x c FROM t_with_1 x


union all


--这里不能用with再次定义,同级只能有1个with,可以写在最前面


--内部with


SELECT y.a ,y.b , (WITH


t_with_x AS (SELECT * FROM t_with_1)


SELECT a FROM t_with_x )


FROM ( WITH


t_with_2 AS (SELECT 1 a ,2 b FROM DUAL)


SELECT a ,b FROM t_with_2


) y


WHERE y.a = (


with t_with_3 AS (SELECT 1 a ,2 b FROM DUAL)


select a from t_with_3


)


)


7.一个with查询的实例:





查询出部门的总薪水大于所有部门平均总薪水的部门。部门表s_dept,员工表s_emp。分析:做这个查询,首先必须计算出所有部门的总薪 水,然后计算出总薪水的平均薪水,再筛选出部门的总薪水大于所有部门总薪水平均薪水的部门。那么第1 步with 查询查出所有部门的总薪水,第2 步用with 从第1 步获得的结果表中查询出平均薪水,最后利用这两次的with 查询比较总薪水大于平均薪水的结果,如下:


with


--step1:查询出部门名和部门的总薪水


dept_costs as(


select a.name,sum(b.salary) dept_total


from


s_dept a,s_emp b


where a.id=b.dept_id


group by a.name


),


--step2:利用上一个with查询的结果,计算部门的平均总薪水


avg_costs as(


select sum(dept_total)/count(*) dept_avg


from dept_costs


)


--step3:从两个with查询中比较并且输出查询结果


select name,dept_total


from dept_costs


where


dept_total>


(


select dept_avg


from


avg_costs


)


order by name;


从上面的查询可以看出,前面的with 查询的结果可以被后面的with查询重用,并且对with 查询的结果列支持别名的使用,在最终查询中必须要引用所有with 查询,否则会报错ora-32035 错误。


再如有这样一个需求:一个查询,如果查询的结果行不满足是10 的倍数,则补空行,直到是查询出的行数是10 的倍数。例如:select * from trademark这个查询。


with子句


3.2 11G R2with新特性





新版本的WITH 允许递归使用,在功能上比原来有了质的飞跃,可以实现许多原来CONNECT BY做不到的事。


3.3 with对执行计划的影响





with子句有可能会改变执行计划。

<select id="selectIntegral" resultMap="IntraMap"
parameterType="com.sgcc.procurement.main.entity.integral.IntegralBean">
WITH TEMP AS
(SELECT C.BP_RULE_FLOW_ID, MAX(C.OPERATE_TIME)
OPERATE_TIME
FROM EC_BP_EXCHANGELOG C
GROUP BY C.BP_RULE_FLOW_ID)
SELECT
A.BP_RULE_FLOW_ID,
A.CORPORATION_ID,
A.APPLICATION_NO,
A.SCALE_MALL,
A.SCALE_PALTFORM,
A.TIME_BEGIN,
A.TIME_END,
<!-- TO_CHAR(A.TIME_BEGIN,'yyyy-mm-dd hh24:mi:ss') as TIME_BEGIN, -->
<!-- TO_CHAR(A.TIME_END,'yyyy-mm-dd hh24:mi:ss') as TIME_END, -->
A.RULE_STATUS,
B.ID,
B.OPERATIOR_TYPE,
B.OPERATIOR,
B.OPERATIOR_NAME,
B.OPERATE_TIME,
<!-- TO_CHAR(B.OPERATE_TIME,'yyyy-mm-dd hh24:mi:ss') as OPERATE_TIME, -->
B.OPERATE_DESC,
B.APPROVE_REMARK
FROM EC_BP_EXCHANGE A,
EC_BP_EXCHANGELOG B, TEMP
WHERE A.BP_RULE_FLOW_ID = B.BP_RULE_FLOW_ID
AND B.BP_RULE_FLOW_ID = TEMP.BP_RULE_FLOW_ID
AND B.OPERATE_TIME =
TEMP.OPERATE_TIME
and A.RULE_STATUS = B.RULE_STATUS
<if test="bpRuleFlowId != null and bpRuleFlowId != ''">
and A.BP_RULE_FLOW_ID =#{bpRuleFlowId,jdbcType=VARCHAR}
</if>
<if test="corporationId != null and corporationId != ''">
and A.CORPORATION_ID= #{corporationId,jdbcType=VARCHAR}
</if>
<if test="applicationNo != null and applicationNo != ''">
and A.APPLICATION_NO= #{applicationNo,jdbcType=VARCHAR}
</if>
<if test="ruleStatus != null and ruleStatus != ''">
and A.RULE_STATUS= #{ruleStatus,jdbcType=VARCHAR}
</if>
<if test="(timeEnd == null or timeEnd == '') and (timeBegin != null and timeBegin != '')">
<![CDATA[
and a.TIME_BEGIN <= #{timeBegin,jdbcType=VARCHAR}
 and  a.TIME_END >= #{timeBegin,jdbcType=VARCHAR} ]]>

</if>
<if test="(timeBegin == null or timeBegin == '') and (timeEnd != null and timeEnd != '')">
<![CDATA[  and a.TIME_BEGIN <= #{timeEnd,jdbcType=VARCHAR}
    and a.TIME_END >= #{timeEnd,jdbcType=VARCHAR} ]]>
</if>
<if test="timeBegin != null and timeBegin != ''and timeEnd != null and timeEnd != ''">
<![CDATA[and ( 
   (a.TIME_BEGIN >= #{timeBegin,jdbcType=VARCHAR} AND a.TIME_BEGIN <= #{timeEnd,jdbcType=VARCHAR} ) OR  
        (a.TIME_BEGIN <= #{timeBegin,jdbcType=VARCHAR} AND a.TIME_END >= #{timeEnd,jdbcType=VARCHAR}) OR  
        (a.TIME_END >= #{timeBegin,jdbcType=VARCHAR} and a.TIME_END <=  #{timeEnd,jdbcType=VARCHAR}) OR 
        (a.TIME_BEGIN >= #{timeBegin,jdbcType=VARCHAR} and a.TIME_END <=  #{timeEnd,jdbcType=VARCHAR})
         )  ]]>
</if>
</select>




这条sql 用到非空条件判断,  <if test="timeBegin != null and timeBegin != ''and timeEnd != null and timeEnd != ''">    
查询头用到  with as  :
3.1 with基础



使用WITH AS 语句可以为一个子查询语句块定义一个名称,使用这个子查询名称可以在查询语句的很多地方引用这个子查询。Oracle 数据库像对待内联视图或临时表一样对待被引用的子查询名称,从而起到一定的优化作用。with子句是9i新增语法。


你可以在任何一个顶层的SELECT 语句以及几乎所有类型的子查询语句前,使用子查询定义子句。被定义的子查询名称可以在主查询语句以及所有的子查询语句中引用,但未定义前不能引用。


with子句中不能嵌套定义<也就是with子句中不能有with子句>,但子查询中出现的子查询定义语句可以引用已定义的子查询名称。<可以引用前面已经定义的with子句>


with子句相关总结:





1.使用with子句可以让子查询重用相同的with查询块,通过select调用(with子句只能被select查询块引用),一般在with查询用到多次情况下。在引用的select语句之前定义,同级只能定义with关键字只能使用一次,多个用逗号分割。


2.with子句的返回结果存到用户的临时表空间中,只做一次查询,反复使用,提高效率。


3.在同级select前有多个查询定义的时候,第1个用with,后面的不用with,并且用逗号隔开。


5.最后一个with 子句与下面的查询之间不能有逗号,只通过右括号分割,with 子句的查询必须用括号括起来


6.如果定义了with子句,而在查询中不使用,那么会报ora-32035 错误:未引用在with子句中定义的查询名。(至少一个with查询的name未被引用,解决方法是移除未被引用的with查询),注意:只要后面有引用 的就可以,不一定非要在主查询中引用,比如后面的with查询也引用了,也是可以的。


7.前面的with子句定义的查询在后面的with子句中可以使用。但是一个with子句内部不能嵌套with子句。


8.当一个查询块名字和一个表名或其他的对象相同时,解析器从内向外搜索,优先使用子查询块名字。


9.with查询的结果列有别名,引用的时候必须使用别名或*。


with子句优点:





1. SQL可读性增强。比如对于特定with子查询取个有意义的名字等。


2. with子查询只执行一次,将结果存储在用户临时表空间中,可以引用多次,增强性能。


with子句语法:


With alias_name as (select1), --as和select中的括号都不能省略


alias_name2 as (select2),--后面的没有with,逗号分割,同一个主查询同级别地方,with子查询只能定义一次




alias_namen as (select n) –与下面的实际查询之间没有逗号


Select ….


with使用例子:


1.一般使用方式





如查询销售部门员工的姓名:


--with clause


with a as


(select id from s_dept where name=Sales order by id)


select last_name,title


from s_emp where dept_id in (select * from a);--使用select查询别名


使用with 子句,可以在复杂的查询中预先定义好一个结果集,然后在查询中反复使用,不使用会报错。而且with 子句获得的是一个临时表,如果在查询中使用,必须采用select from with 查询名,比如


With cnt as(select count(*) from table)


Select cnt+1 from dual;


是错误的。必须是


With cnt as(select count(*) shumu from user_tables)


Select shumu+1 from cnt;


2.在大多数子查询中引用,同级可见





再如下面两个语句含义等价:


with a as (select trade_id,name from product) --使用之前定义


select name from a where a.trade_id in (


with b as (select id from trademark where id=1) --使用之前定义


select id from b


);


select name from product where trade_id in (select id from trademark where id=1);


3. with子查询不可嵌套定义,但是后面的with定义可以引用前面的结果集。





with select_trade as (select trade_id from product where id=1),


--后面的with子查询可以引用前面的结果


select_trademark as (select name from trademark where id=(select trade_id from select_trade))


select * from select_trademark;


--这条语句错误


with select_trade as


--with中有嵌套with,不允许


( with temp as ( select trade_id from product where id=1)


select trade_id from temp


),


select_trademark as (select name from trademark where id=(select trade_id from select_trade))


select * from select_trademark;


4. 同级定义,只能有一个with





with a as (select trade_id from product),


b as (select id from trademark where rownum<3) --第2个定义不用with


select trade_id from a


minus


select id from b;


5. 在大多数子查询中定义和使用,一个复杂的例子





SELECT a ,b


FROM (


--第1个定义t_with


WITH


t_with AS (SELECT 1 a FROM DUAL)


--子查询使用t_with


SELECT x.a ,(


--内部定义了个t_with_z,并且使用t_with


WITH t_with_z as (SELECT 1 a FROM t_with )


SELECT s_1.a FROM t_with_z s_1 ,t_with s_2


6. 集合中使用with子查询





--这个是错误的,同级只能有一个with定义,当然两个可以写在一起。


SELECT *


FROM (


WITH


t_with_1 AS (SELECT 1 a ,1 b FROM DUAL)


--此后的整个语句被认为是一个主查询语句


SELECT x.a , x.b FROM t_with_1 x


union all


WITH -- 此处再次出现定义


t_with_2 AS (SELECT 1 a ,2 b FROM DUAL)


SELECT y.a ,y.b FROM t_with_2 y


--正确


SELECT *


FROM (


--第1个with


WITH


t_with_1 AS (SELECT 1 a ,1 b FROM DUAL)


SELECT x.a , x.b ,x c FROM t_with_1 x


union all


--这里不能用with再次定义,同级只能有1个with,可以写在最前面


--内部with


SELECT y.a ,y.b , (WITH


t_with_x AS (SELECT * FROM t_with_1)


SELECT a FROM t_with_x )


FROM ( WITH


t_with_2 AS (SELECT 1 a ,2 b FROM DUAL)


SELECT a ,b FROM t_with_2


) y


WHERE y.a = (


with t_with_3 AS (SELECT 1 a ,2 b FROM DUAL)


select a from t_with_3


)


)


7.一个with查询的实例:





查询出部门的总薪水大于所有部门平均总薪水的部门。部门表s_dept,员工表s_emp。分析:做这个查询,首先必须计算出所有部门的总薪 水,然后计算出总薪水的平均薪水,再筛选出部门的总薪水大于所有部门总薪水平均薪水的部门。那么第1 步with 查询查出所有部门的总薪水,第2 步用with 从第1 步获得的结果表中查询出平均薪水,最后利用这两次的with 查询比较总薪水大于平均薪水的结果,如下:


with


--step1:查询出部门名和部门的总薪水


dept_costs as(


select a.name,sum(b.salary) dept_total


from


s_dept a,s_emp b


where a.id=b.dept_id


group by a.name


),


--step2:利用上一个with查询的结果,计算部门的平均总薪水


avg_costs as(


select sum(dept_total)/count(*) dept_avg


from dept_costs


)


--step3:从两个with查询中比较并且输出查询结果


select name,dept_total


from dept_costs


where


dept_total>


(


select dept_avg


from


avg_costs


)


order by name;


从上面的查询可以看出,前面的with 查询的结果可以被后面的with查询重用,并且对with 查询的结果列支持别名的使用,在最终查询中必须要引用所有with 查询,否则会报错ora-32035 错误。


再如有这样一个需求:一个查询,如果查询的结果行不满足是10 的倍数,则补空行,直到是查询出的行数是10 的倍数。例如:select * from trademark这个查询。


with子句


3.2 11G R2with新特性





新版本的WITH 允许递归使用,在功能上比原来有了质的飞跃,可以实现许多原来CONNECT BY做不到的事。


3.3 with对执行计划的影响





with子句有可能会改变执行计划。

出现这个错误的原因是在导入seaborn包时,无法从typing模块中导入名为'Protocol'的对象。 解决这个问题的方法有以下几种: 1. 检查你的Python版本是否符合seaborn包的要求,如果不符合,尝试更新Python版本。 2. 检查你的环境中是否安装了typing_extensions包,如果没有安装,可以使用以下命令安装:pip install typing_extensions。 3. 如果你使用的是Python 3.8版本以下的版本,你可以尝试使用typing_extensions包来代替typing模块来解决该问题。 4. 检查你的代码是否正确导入了seaborn包,并且没有其他导入错误。 5. 如果以上方法都无法解决问题,可以尝试在你的代码中使用其他的可替代包或者更新seaborn包的版本来解决该问题。 总结: 出现ImportError: cannot import name 'Protocol' from 'typing'错误的原因可能是由于Python版本不兼容、缺少typing_extensions包或者导入错误等原因造成的。可以根据具体情况尝试上述方法来解决该问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [ImportError: cannot import name ‘Literal‘ from ‘typing‘ (D:\Anaconda\envs\tensorflow\lib\typing....](https://blog.youkuaiyun.com/yuhaix/article/details/124528628)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值