SQL性能区别(1)——union(all)、in/exists、join on/where、row_number/rank、group by/distinct

本文深入解析SQL中的union与unionall、in与exist、leftjoin与where等关键操作的区别及性能对比,同时探讨ROW_NUMBER()、RANK()、DENSE_RANK()的用法与groupby、distinct的效率分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0. 前言

本文注重的,是SQL通用设计思想及性能使用上的区别,忽略了不同类型的SQL语法区别,例如ANSI-SQL、MySQL,SQL Server,Oracle,甚至是Hive,Impala,Presto。[反正只要是我用到、碰到的…]

1. union 和 union all的区别

参考来源:
SQL语句中:UNION与UNION ALL的区别
数据库中UNION和UNION ALL的区别以及并集怎么取得
关于Union和Union All的区别以及用法

先说说这两个用法的要求:
必须选择相同数量的列,每条select语句中的列的顺序也必须相同,这些列也必须拥有相似的数据类型。

也就是说,要达到六耳猕猴和通背猿猴的那种匹配度才能union (all),这是前提。

这两个关键字都是将两个结果集合并成一个

union 是在进行表链接后,筛选掉完全相同的记录,union all不会去重,记录可能有重复;

union 会按照select 字段的顺序进行排序(默认),union all 只是简单的将两个结果集合并就返回,并不排序;

所以效率上来说,union all 要比union 快很多,在确认合并的两个结果集总不包含重复数据且不需要排序的话,使用union all;

另外,
这两个操作中,select的列名不一定要一样,如果要对进行排序,不需要在每一个select结果集中排序,只需要在最后一条语句中使用order by 进行排序即可。

select pname,ename from emp 
union 
select username,dname from dept
order by ename;

简要回答:
UNION去重且排序
UNION ALL不去重不排序

来个栗子

现在有两张表:
table
1.union 测试
union可以看到这里面有两个令狐冲,不是说会去重的嘛?!

大家看清楚了,这段SQL中含有的字段包括了课程名字和老师名字,虽然令狐冲只有一个,但是这两个字段都不一样,所以不是重复的记录,所以这也就是我上面说,完全相同

那就来个去重的栗子尝一下

union2这些应该学乖了吧,select中只有前两个字段,这样令狐冲记录就是重复的,所以只显示一条记录!

所以,如果要使用union,要想想自己只是想看看有哪些学生,还是要看所有信息,在select字段中选择。

2.union all测试
不好意思哈,参考来源中没做,我也懒得自己建表去测了哈哈哈~~
不过可以想到,不管选哪几个字段,都会有两个令狐冲的记录的。

注意;
Hive 1.2.0之前的版本仅支持UNION ALL,其中重复的行不会被删除,而且不支持在顶层使用,只能在子查询中用。
也就是

1. 报错
select xx from t1
union all
select xx from t2

2. 成功
select * 
from (select xx from t1
	   union all
	  select xx from t2	
		)
2. (not)in 和 exist 的区别

参考来源:
浅谈sql中的in与not in,exists与not exists的区别以及性能分析
浅谈sql中的in与not in,exists与not exists的区别
SQL查询~ 存在一个表而不在另一个表中的数据
SQL中如何使用EXISTS替代IN

Hive不支持where语句中的 in/exists条件,可以使用 left semi-join 语法。

先放一下这两条语句是怎么用的

select t1.* from t1 where t1.id in (select t2.id from t2)

select t1.* from t1 where exists (select t2.id from t2 where t2.id = t1.id)

再看一下,我的测试过程:

  1. 一百多万条记录时,前面的表大,后面的表较小。两个表相差不大的情况下,可以看到,其实效率也差不多,单纯从数字上来看, 甚至 in 还要快一点。
    在这里插入图片描述
  2. 千万,亿级条数,
    在这里插入图片描述这就很奇怪了,为什么都说exists效率比in快呢,我这边测试下来,都没发生很大变化,时间原因,本次探索到此。
3. left join on与where的用法与区别
3.1 left join on and 和where的执行顺序与结果区别

left join on and 与 left join on where的区别

假设有两个表
在这里插入图片描述执行以下两条SQL

1select * 
          from tab1 
     left join tab2 
            on tab1.size = tab2.size 
         where tab2.name='AAA'
	2select * 
	      from tab1 
     left join tab2 
	        on tab1.size = tab2.size 
	       and tab2.name='AAA'

咱来看下结果哈。可以自己先猜一下。

第一条SQL的过程:

1、中间表
on条件: tab1.size = tab2.size,生成的结果
在这里插入图片描述
这就是正常的左连接,无论右边表的字段啥样,都会按照左边表的字段输出。join完毕生成一张中间表。

2、再对中间表过滤
where 条件: tab2.name=’AAA’
在这里插入图片描述
此时进行的where条件就和join没任何关系了,所以结果就只有这一条。

第二条SQL的过程:

1、中间表
on条件: tab1.size = tab2.size and tab2.name=’AAA’
在这里插入图片描述
这里可以看到,on中的条件只对右边的表进行了过滤,对左边的表毫无影响,所以才会出现这样的结果。

其实以上结果的关键原因就是 left join,right join,full join 的特殊性,不管on上的条件是否为真都会返回 left 或 right 表中的记录,full则具有left和right的特性的并集。

而inner jion没这个特殊性,则条件放在on中和where中,返回的结果集是相同的。

简单概括一下:

  • 先on 再 where是对两个表join后的结果进行where筛选
  • on and只能对join右边的表进行筛选,对左边表无影响
3.2 同样结果,使用left join 比直接使用where速度快

参考来源:
使用left join比直接使用where速度快的原因
亲测SQL left join on 和 where 效率

这个问题我看网上的帖子很少,我是在自己碰到的,发现有时候同一个结果,用 left join 和 where 都可以。

先煮个栗子。

例如下面这几张表:

t1 (s_id, s_name, s_dep, s_age)
学号,学员姓名,所属单位,学员年龄

t2 (s_id, c_id, grade)
学号,课程编号,学习成绩

--查询选修课程编号为’C5’的学员姓名和所属单位?
--1. 使用left join on
   select t1.s_name
		  ,t1.s_dep
     from t1
left join t2
	   on t2.s_id = t1.s_id
	where t2.c_id = "C2"

--2. 使用where 
   select s_name
   		  ,s_dep
   	 from t1,t2
    where t1.s_id = t2.s_id
      and t2.c_id = "C2"

我在写时,习惯性的用 left join,可能是在公司中见到的 left join比较多,都忘了也可以用 where来这么实现了。

那么,这两个sql有啥区别么?

按照参考文章中的说法:

多表使用left join只是把主表里的所有数据查询出来,其他表只查询表中的符合条件的某一条记录,所以速度非常快;而多表使用where内联,是把所有表的数据全查出来,然后进行比对,所以速度非常慢。

2019-05-05更新

原答案是这样:

在这里插入图片描述
看到牛客网讨论区这么说:
在这里插入图片描述

这么看来,还是实践出真知啊,实习中学的比看书来的直接。

4. ROW_NUMBER()和RANK(),DENSE_RANK()区别

参考来源:
一个SQL语句分清楚RANK(),DENSE_RANK(),ROW_NUMBER()三个排序的不同
sql 四大排名函数—(ROW_NUMBER、RANK、DENSE_RANK、NTILE)简介

先看个栗子:

写几句SQL

SELECT s.deptno
	   ,s.ename,s.sal,
	   RANK() over(partition by s.deptno order by s.sal) as rank,
	   DENSE_RANK() over(partition by s.deptno order by s.sal) as dense_rank,
	   ROW_NUMBER() over(partition by s.deptno order by s.sal) as row_number
  FROM emp s;

在这里插入图片描述总结一下:

rank 根据order by排名 会出现并列排名。下一个值会跳过并列值 比如 1 2 2 4 5

通常对应rank还有 dense_rank 出现并列排名以后,下一个值不跳过并列值 1 2 2 3 4

row_number 就是直接排出一个名次。不会出现并列排名 1 2 3 4 5

5. group by与distinct效率分析及优化措施

参考来源:
group by与distinct效率分析及优化措施
SQL中Distinct和group by性能区别

在去重计数的时候,一般有两种方法:

--1. count(distinct)
select count(distinct t.user_id) from idw.fact_borrows t

--2. group by
select count(*) from (select t.user_id from idw.fact_borrows t group by t.user_id) t2

根据参考博客,和本人实测(实验环境为HUE上的 Impala查询,实际生产数据),先说本文得到的结论:

  1. 当不同记录的数量较小时,group by 要明显快于 count(distinct);
  2. 当不同记录的数量较大时,count(distinct)反而要更快

实验记录:

  1. 结果数据集只有一百多万个时:
    在这里插入图片描述

  2. 结果数据集达到一千多万时:
    在这里插入图片描述

这里的秒数,都是我多跑了好几次,取的众数。

OK,那就按照参考博客的原因来总结一下原因。

因为当结果数据集较小的时候,执行计划会使用HashAggregation,在内存中维护一个Hash表,而当结果集较大时,无法通过在内存中维护Hash表的方式使用HashAggregation,planner会使用GroupAggregation,并会用到排序,而且因为目标数据集太大,无法在内存中使用Quick Sort,而要在外存中使用Merge Sort,而这就极大的增加了I/O开销。

(其实这么一段话我也不是很清楚其原理)

优化 SELECT * FROM ( SELECT TMP_PAGE.*, ROWNUMBER() OVER() AS PAGEHELPER_ROW_ID FROM ( SELECT a.acptCode AS acptCode, a.tms FROM ( SELECT dai.ACPT_CODE AS acptCode, ( SELECT aply.UDT_TMS FROM OCRM_F_CM_FLOW_APLY aply WHERE aply.APLY_ID = dai.APLY_ID) AS tms FROM OCRM_F_MK_DTY_APLY_INF dai WHERE dai.BSN_TYPE IN ('1', '2', '5') AND dai.APLY_ID IN ( SELECT aply.APLY_ID FROM OCRM_F_CM_FLOW_APLY aply WHERE aply.APRV_STAT = '003' AND aply.UDT_ORG IN ( SELECT REL3.INN_ORG_ID FROM OCRM_F_CM_ORG_REL_HRCH_A REL3 WHERE 1 = 1 AND (REL3.Fst_Lvl_Brch_Org_Id = '703220' OR REL3.INN_ORG_ID ='703220') ) AND aply.CRT_ORG ='703220' ) UNION SELECT dai.ACPT_CODE AS acptCode, ( SELECT aply.UDT_TMS FROM OCRM_F_CM_FLOW_APLY aply WHERE aply.APLY_ID = dai.APLY_ID) AS tms FROM OCRM_F_MK_DTY_APLY_INF dai LEFT JOIN OCRM_F_CI_CUST_TEAM team ON team.CUST_NUM = dai.CUST_NUM AND team.BANK_NUM = dai.BANK_NUM WHERE dai.BSN_TYPE IN ('1', '2', '5') AND team.TEAM_MEBR_TYP IN ('01', '02') AND team.TEAM_MEBR_AFLT_FIGBR_ORGN_NUM = '703220' AND dai.APLY_ID IN ( SELECT aply.APLY_ID FROM OCRM_F_CM_FLOW_APLY aply WHERE aply.APRV_STAT = '003' AND aply.CRT_ORG ='703220' ) UNION SELECT b.acptCode, b.tms FROM ( SELECT dai.ACPT_CODE AS acptCode , ( SELECT mark.MAIN_BLONG_ID FROM OCRM_F_CI_BRANCH_MARKETER_INF mark WHERE mark.CUST_ID = dai.CUST_NUM FETCH FIRST 1 ROWS ONLY ) AS orgId, ( SELECT aply.UDT_TMS FROM OCRM_F_CM_FLOW_APLY aply WHERE aply.APLY_ID = dai.APLY_ID) AS tms FROM OCRM_F_MK_DTY_APLY_INF dai WHERE dai.BSN_TYPE IN('1', '2', '5') AND dai.APLY_ID IN ( SELECT aply.APLY_ID FROM OCRM_F_CM_FLOW_APLY aply WHERE aply.APRV_STAT = '003' AND aply.CRT_ORG ='703220' ) ) b WHERE b.orgId IN ( SELECT rel.INN_ORG_ID FROM OCRM_F_CM_ORG_REL_HRCH_A rel WHERE 1 = 1 AND (rel.Fst_Lvl_Brch_Org_Id ='703220' OR rel.INN_ORG_ID ='703220') ) ) a ORDER BY a.tms DESC WITH UR ) AS TMP_PAGE) TMP_PAGE WHERE PAGEHELPER_ROW_ID BETWEEN 1 AND 10
最新发布
08-13
select * from( with vtailratio_tmp as ( select distinct d.*,e.OPERATE_WAY,e.min_tail_fare,e.YEAR_DAY,e.TAIL_COMMISSION_RATIO,e.AREA_FLAG,e.MIN_HOSTING,e.ENABLE_DATE,e.MAX_HOSTING from distributor_fund_protocol d, (select a.fund_code,a.distributor_code, nvl(c.OPERATE_WAY,b.OPERATE_WAY) OPERATE_WAY, 0.00 min_tail_fare, decode(nvl(c.YEAR_DAY,b.YEAR_DAY), '365', '1', '2', '0', '3', '3', '0', '2' ) YEAR_DAY, nvl(c.TAIL_COMMISSION_RATIO,b.TAIL_COMMISSION_RATIO) TAIL_COMMISSION_RATIO, nvl(c.AREA_FLAG,b.AREA_FLAG) AREA_FLAG, nvl(c.MIN_HOSTING,b.MIN_HOSTING) MIN_HOSTING, nvl(c.ENABLE_DATE,b.ENABLE_DATE) ENABLE_DATE, nvl(c.MAX_HOSTING,b.MAX_HOSTING) MAX_HOSTING from (select fund_code,distributor_code from fund_info,distributor_info) a, (select * from TAIL_COMMISSION_FARE_SET_ORI where DISTRIBUTOR_CODE = '***') b, (select * from TAIL_COMMISSION_FARE_SET_ORI where DISTRIBUTOR_CODE <> '***') c where a.fund_code = c.fund_code(+) and a.DISTRIBUTOR_CODE = c.DISTRIBUTOR_CODE(+) and a.fund_code = b.fund_code(+) )e where d.fund_code = e.fund_code and d.distributor_code = e.distributor_code ) select a.distributor_code distributor_code,di.distributor_name,a.fund_code fundcode,fi.fund_name,to_char(replace(sum(BALANCE), ','),'FM999,999,999,999,990.00')balance,to_char(replace(sum(SHARES), ','),'FM999,999,999,999,990.00') shares,to_char(replace(avg(balance), ','),'FM999,999,999,999,990.00') avgbalance,to_char(replace(sum(fee), ','),'FM999,999,999,999,990.00') fee, sum(income) income, avg(shares) avgshares, tfa.min_tail_fare,case when sum(fee)>=tfa.min_tail_fare then sum(fee) else 0 end paid_fee, to_char(nvl(TAIL_COMMISSION_RATIO,0)*100,'fm999999990.0099999')||'%' TAIL_COMMISSION_RATIO from( select distributor_code, fund_code, TRANSACTION_CFM_DATE,sum(balance) balance, sum(shares) shares, sum(fee) fee, sum(TAIL_COMMISSION_RATIO) TAIL_COMMISSION_RATIO,sum(income) income,avg(balance) avgbalance,avg(shares) avgshares from( select distributor_code, fund_code, TRANSACTION_CFM_DATE, share_class, sum(BALANCE) BALANCE, sum(SHARES) SHARES, sum(round(BALANCE /(case when YEAR_DAY>0 then YEAR_DAY else year.YearDays end)* nvl(TAIL_COMMISSION_RATIO, 0), 2)) fee, max(nvl(TAIL_COMMISSION_RATIO, 0)) TAIL_COMMISSION_RATIO, sum(nvl(income, 0)) income, avg(BALANCE) avgbalance, avg(SHARES) avgshares from( SELECT A.distributor_code, A.fund_code, 'A' share_class, A.TRANSACTION_CFM_DATE, decode(b.OPERATE_WAY, '0',a.balance, '1',nvl(A.balance, 0) - nvl(A.REINVEST_BALANCE, 0), '2',nvl(A.ORI_HOLD_BALANCE, 0), '3',nvl(A.ORI_HOLD_BALANCE, 0) - nvl(A.ORI_REINVEST_BALANCE, 0)) BALANCE, decode(b.OPERATE_WAY, '0',a.shares, '1',nvl(A.shares, 0) - nvl(A.REINVEST_SHARE, 0), '2',nvl(A.shares, 0), '3',nvl(A.shares, 0) - nvl(A.REINVEST_SHARE, 0)) SHARES, B.TAIL_COMMISSION_RATIO, A.income, nvl(b.YEAR_DAY,0) YEAR_DAY FROM( select a.distributor_code, a.fund_code, 'A' share_class, a.TRANSACTION_CFM_DATE, a.HOLD_DATE, a.HOLD_RATIO, nvl(a.income, 0) income, nvl(a.REINVEST_SHARE, 0) REINVEST_SHARE, nvl(a.REINVEST_BALANCE, 0) REINVEST_BALANCE, nvl(a.ORI_HOLD_BALANCE, 0) ORI_HOLD_BALANCE, NVL(A.ORI_REINVEST_BALANCE, 0) ORI_REINVEST_BALANCE, case when b.ACC_INCOME_TO_SHARE_FLAG = '0' or /** #TACode || **/ '94'||a.distributor_code = '48002' then nvl(a.HOLD_BALANCE, 0) else nvl(a.HOLD_BALANCE, 0) + nvl(a.income, 0) end balance, case when b.ACC_INCOME_TO_SHARE_FLAG = '0' or /** #TACode || **/ '94'||a.distributor_code = '48002' then nvl(a.HOLD_SHARE, 0) else nvl(a.HOLD_SHARE, 0) + nvl(a.income, 0) end shares from FUND_SALE_STAT a,fund_info b WHERE a.INDIVIDUAL_OR_INSTITUTION = '*' and A.TRANSACTION_CFM_DATE >= {"origin" :"param", "field" :"dateStart","where" :"%s"} and a.TRANSACTION_CFM_DATE <= {"origin" :"param", "field" :"dateEnd","where" :"%s"} and a.fund_code = b.fund_code ) A, ( select fund_code, distributor_code, AREA_FLAG, MIN_HOSTING, MAX_HOSTING, TAIL_COMMISSION_RATIO, ENABLE_DATE,OPERATE_WAY,YEAR_DAY, last_value(end_date)over(partition by fund_code, distributor_code, ENABLE_DATE order by end_date rows between unbounded preceding and unbounded following) end_date from(select fund_code, distributor_code, AREA_FLAG, MIN_HOSTING, MAX_HOSTING, TAIL_COMMISSION_RATIO, ENABLE_DATE,OPERATE_WAY,YEAR_DAY, nvl(lead(ENABLE_DATE)over(partition by fund_code, distributor_code order by ENABLE_DATE, MIN_HOSTING), '20991231') end_date from vtailratio_tmp where AREA_FLAG in ('0','1') ) ) B where A.fund_code = B.fund_code AND A.distributor_code = B.distributor_code and A.HOLD_DATE >= B.ENABLE_DATE and A.HOLD_DATE < B.end_date AND decode(b.OPERATE_WAY, '0',a.balance, '1',nvl(A.balance, 0) - nvl(A.REINVEST_BALANCE, 0), '2',nvl(A.ORI_HOLD_BALANCE, 0), '3',nvl(A.ORI_HOLD_BALANCE, 0) - nvl(A.ORI_REINVEST_BALANCE, 0)) > B.MIN_HOSTING AND decode(b.OPERATE_WAY, '0',a.balance, '1',nvl(A.balance, 0) - nvl(A.REINVEST_BALANCE, 0), '2',nvl(A.ORI_HOLD_BALANCE, 0), '3',nvl(A.ORI_HOLD_BALANCE, 0) - nvl(A.ORI_REINVEST_BALANCE, 0)) <= B.MAX_HOSTING and DECODE(B.AREA_FLAG,'2', a.HOLD_RATIO, '1', DECODE(b.OPERATE_WAY, '0', SHARES, '1', A.SHARES - A.REINVEST_SHARE, '2', SHARES, '3', A.SHARES - A.REINVEST_SHARE), DECODE(b.OPERATE_WAY, '0', A.BALANCE, '1', A.BALANCE - A.REINVEST_BALANCE, '2', a.ORI_HOLD_BALANCE, '3', A.ORI_HOLD_BALANCE - A.ORI_REINVEST_BALANCE)) >= B.MIN_HOSTING and DECODE(B.AREA_FLAG,'2', a.HOLD_RATIO, '1', DECODE(b.OPERATE_WAY, '0', SHARES, '1', A.SHARES - A.REINVEST_SHARE, '2', SHARES, '3', A.SHARES - A.REINVEST_SHARE), DECODE(b.OPERATE_WAY, '0', A.BALANCE, '1', A.BALANCE - A.REINVEST_BALANCE, '2', a.ORI_HOLD_BALANCE, '3', A.ORI_HOLD_BALANCE - A.ORI_REINVEST_BALANCE)) < B.MAX_HOSTING and not exists( select * from GRADING_FUND_PLAN tsc where tsc.MAIN_FUND_CODE = A.fund_code and tsc.SECTION_FUND_CODE = '******' ) and a.transaction_cfm_date >= {"origin" :"param", "field" :"dateStart","where" :"%s"} and a.transaction_cfm_date <= {"origin" :"param", "field" :"dateEnd","where" :"%s"} {"origin" :"param", "field":"agencyCodeList", "where" :" and a.distributor_code in (%s)"} {"origin" :"param", "field" :"fundCodeList", "where" :" and a.fund_code in (%s)"} /** and #WhereSql **/ ) hz , (select case when substr({"origin" :"param", "field" :"dateStart","where" :"%s"}, 1, 4)=substr({"origin" :"param", "field" :"dateEnd","where" :"%s"}, 1, 4) and mod(substr({"origin" :"param", "field" :"dateEnd","where" :"%s"}, 1, 4),4)=0 then '366' else '365' end YearDays from dual) year where GetSysValueRX('System','TailSegment','0')=0 and GetSysValueRX('System','TailMode','1')=1 group by distributor_code,fund_code,share_class,TRANSACTION_CFM_DATE union all select distributor_code, fund_code, TRANSACTION_CFM_DATE, share_class, sum(BALANCE) BALANCE, sum(SHARES) SHARES, sum(round(BALANCE / (case when YEAR_DAY>0 then YEAR_DAY else year.YearDays end) * nvl(TAIL_COMMISSION_RATIO, 0), 2)) fee, max(nvl(TAIL_COMMISSION_RATIO, 0)) TAIL_COMMISSION_RATIO, sum(nvl(income, 0)) income, avg(BALANCE) avgbalance, avg(SHARES) avgshares from( SELECT a.distributor_code, a.fund_code, 'A' share_class, a.TRANSACTION_CFM_DATE, decode(e.OPERATE_WAY, '0',a.balance, '1',nvl(a.balance, 0) - nvl(a.REINVEST_BALANCE, 0), '2',nvl(a.ORI_HOLD_BALANCE, 0), '3',nvl(a.ORI_HOLD_BALANCE, 0) - nvl(a.ORI_REINVEST_BALANCE, 0)) BALANCE, decode(e.OPERATE_WAY, '0',a.shares, '1',nvl(a.shares, 0) - nvl(a.REINVEST_SHARE, 0), '2',nvl(a.shares, 0), '3',nvl(a.shares, 0) - nvl(a.REINVEST_SHARE, 0)) SHARES, E.TAIL_COMMISSION_RATIO, a.income, nvl(e.YEAR_DAY,0) YEAR_DAY FROM( select a.distributor_code, a.fund_code, 'A' share_class, a.TRANSACTION_CFM_DATE, a.HOLD_DATE, a.HOLD_RATIO, nvl(a.income, 0) income, nvl(a.REINVEST_SHARE, 0) REINVEST_SHARE, nvl(a.REINVEST_BALANCE, 0) REINVEST_BALANCE, nvl(a.ORI_HOLD_BALANCE, 0) ORI_HOLD_BALANCE, NVL(A.ORI_REINVEST_BALANCE, 0) ORI_REINVEST_BALANCE, case when b.ACC_INCOME_TO_SHARE_FLAG = '0' or /** #TACode || **/ '94'||a.distributor_code = '48002' then nvl(a.HOLD_BALANCE, 0) else nvl(a.HOLD_BALANCE, 0) + nvl(a.income, 0) end balance, case when b.ACC_INCOME_TO_SHARE_FLAG = '0' or /** #TACode || **/ '94'||a.distributor_code = '48002' then nvl(a.HOLD_SHARE, 0) else nvl(a.HOLD_SHARE, 0) + nvl(a.income, 0) end shares from FUND_SALE_STAT a,fund_info b WHERE a.INDIVIDUAL_OR_INSTITUTION = '*' and A.TRANSACTION_CFM_DATE >= {"origin" :"param", "field" :"dateStart","where" :"%s"} and a.TRANSACTION_CFM_DATE <= {"origin" :"param", "field" :"dateEnd","where" :"%s"} and a.fund_code = b.fund_code ) a, vtailratio_tmp tfa, (select A.TRANSACTION_CFM_DATE,b.TAIL_COMMISSION_RATIO, a.distributor_code, a.fund_code, B.ENABLE_DATE, B.end_date, b.YEAR_DAY, b.OPERATE_WAY from( select a.distributor_code, a.fund_code, 'A' share_class, a.TRANSACTION_CFM_DATE, a.HOLD_DATE, a.HOLD_RATIO, nvl(a.income, 0) income, nvl(a.REINVEST_SHARE, 0) REINVEST_SHARE, nvl(a.REINVEST_BALANCE, 0) REINVEST_BALANCE, nvl(a.ORI_HOLD_BALANCE, 0) ORI_HOLD_BALANCE, NVL(A.ORI_REINVEST_BALANCE, 0) ORI_REINVEST_BALANCE, case when b.ACC_INCOME_TO_SHARE_FLAG = '0' or /** #TACode || **/ '94'||a.distributor_code = '48002' then nvl(a.HOLD_BALANCE, 0) else nvl(a.HOLD_BALANCE, 0) + nvl(a.income, 0) end balance, case when b.ACC_INCOME_TO_SHARE_FLAG = '0' or /** #TACode || **/ '94'||a.distributor_code = '48002' then nvl(a.HOLD_SHARE, 0) else nvl(a.HOLD_SHARE, 0) + nvl(a.income, 0) end shares from FUND_SALE_STAT a,fund_info b WHERE a.INDIVIDUAL_OR_INSTITUTION = '*' and A.TRANSACTION_CFM_DATE >= {"origin" :"param", "field" :"dateStart","where" :"%s"} and a.TRANSACTION_CFM_DATE <= {"origin" :"param", "field" :"dateEnd","where" :"%s"} and a.fund_code = b.fund_code ) a, (select fund_code, distributor_code, AREA_FLAG, MIN_HOSTING, MAX_HOSTING, TAIL_COMMISSION_RATIO, ENABLE_DATE,OPERATE_WAY,YEAR_DAY, last_value(end_date)over(partition by fund_code, distributor_code, ENABLE_DATE order by end_date rows between unbounded preceding and unbounded following) end_date from( select fund_code, distributor_code, AREA_FLAG, MIN_HOSTING, MAX_HOSTING, TAIL_COMMISSION_RATIO, ENABLE_DATE,OPERATE_WAY,YEAR_DAY, nvl(lead(ENABLE_DATE)over(partition by fund_code, distributor_code order by ENABLE_DATE, MIN_HOSTING), '20991231') end_date from vtailratio_tmp where AREA_FLAG in ('0','1') ) ) b WHERE b.fund_code = a.fund_code and b.distributor_code = a.distributor_code and a.HOLD_DATE >= B.ENABLE_DATE and a.HOLD_DATE < B.end_date group by a.distributor_code, a.fund_code, B.AREA_FLAG, B.TAIL_COMMISSION_RATIO, B.MIN_HOSTING, B.MAX_HOSTING, B.ENABLE_DATE, B.end_date,A.TRANSACTION_CFM_DATE,B.YEAR_DAY,b.OPERATE_WAY having DECODE(B.AREA_FLAG,'2', avg(a.HOLD_RATIO), '1', AVG(DECODE(b.OPERATE_WAY, '0', SHARES, '1', A.SHARES - A.REINVEST_SHARE, '2', SHARES, '3', A.SHARES - A.REINVEST_SHARE)), AVG(DECODE(b.OPERATE_WAY, '0', A.BALANCE, '1', A.BALANCE - A.REINVEST_BALANCE, '2', a.ORI_HOLD_BALANCE, '3', A.ORI_HOLD_BALANCE - A.ORI_REINVEST_BALANCE))) >= B.MIN_HOSTING and DECODE(B.AREA_FLAG,'2', avg(a.HOLD_RATIO), '1', AVG(DECODE(b.OPERATE_WAY, '0', SHARES, '1', A.SHARES - A.REINVEST_SHARE, '2', SHARES, '3', A.SHARES - A.REINVEST_SHARE)), AVG(DECODE(b.OPERATE_WAY, '0', A.BALANCE, '1', A.BALANCE - A.REINVEST_BALANCE, '2', a.ORI_HOLD_BALANCE, '3', A.ORI_HOLD_BALANCE - A.ORI_REINVEST_BALANCE))) < B.MAX_HOSTING ) e WHERE a.distributor_code = e.distributor_code(+) and a.fund_code = e.fund_code(+) AND A.TRANSACTION_CFM_DATE = E.TRANSACTION_CFM_DATE and a.fund_code = tfa.fund_code and a.distributor_code = tfa.distributor_code and a.HOLD_DATE >= e.ENABLE_DATE(+) and a.HOLD_DATE < e.end_date(+) and not exists(select * from GRADING_FUND_PLAN tsc where tsc.MAIN_FUND_CODE = a.fund_code and tsc.SECTION_FUND_CODE = '******') and a.transaction_cfm_date >= {"origin" :"param", "field" :"dateStart","where" :"%s"} and a.transaction_cfm_date <= {"origin" :"param", "field" :"dateEnd","where" :"%s"} {"origin" :"param", "field":"agencyCodeList", "where" :" and a.distributor_code in (%s)"} {"origin" :"param", "field" :"fundCodeList", "where" :" and a.fund_code in (%s)"} /** and #WhereSql **/ ) hz, (select case when substr({"origin" :"param", "field" :"dateStart","where" :"%s"}, 1, 4)=substr({"origin" :"param", "field" :"dateEnd","where" :"%s"}, 1, 4) and mod(substr({"origin" :"param", "field" :"dateEnd","where" :"%s"}, 1, 4),4)=0 then '366' else '365' end YearDays from dual) year where GetSysValueRX('System','TailSegment','0')=0 and GetSysValueRX('System','TailMode','1')=2 group by distributor_code,fund_code,share_class,TRANSACTION_CFM_DATE union all select distributor_code, fund_code, TRANSACTION_CFM_DATE, share_class, BALANCE, SHARES, fee, TAIL_COMMISSION_RATIO, income, avgbalance, avgshares from( select distributor_code, fund_code, TRANSACTION_CFM_DATE, share_class, sum(BALANCE) BALANCE, sum(SHARES) SHARES, sum(nvl(( select round(sum(DECODE(AREA_FLAG,'2',ROUND(SUM(GREATEST(LEAST(m.MAX_HOSTING-m.MIN_HOSTING,HZA.BALANCE-m.MIN_HOSTING),0)*TAIL_COMMISSION_RATIO/(case when hzA.YEAR_DAY>0 then hzA.YEAR_DAY else year.YearDays end)),2), '1',ROUND(SUM(GREATEST(LEAST(m.MAX_HOSTING-m.MIN_HOSTING,HZA.SHARES-m.MIN_HOSTING),0)*hzA.NAV*TAIL_COMMISSION_RATIO/(case when hzA.YEAR_DAY>0 then hzA.YEAR_DAY else year.YearDays end)),2), ROUND(SUM(greatest(least(m.MAX_HOSTING - m.MIN_HOSTING,hzA.BALANCE- m.MIN_HOSTING),0) * TAIL_COMMISSION_RATIO / 365)),2)),2) from( select fund_code, distributor_code, AREA_FLAG, MIN_HOSTING, MAX_HOSTING, TAIL_COMMISSION_RATIO, ENABLE_DATE, last_value(end_date)over(partition by fund_code, distributor_code, ENABLE_DATE order by end_date rows between unbounded preceding and unbounded following) end_date from( select fund_code, distributor_code, AREA_FLAG, MIN_HOSTING, MAX_HOSTING, TAIL_COMMISSION_RATIO, ENABLE_DATE, nvl(lead(ENABLE_DATE)over(partition by fund_code, distributor_code order by ENABLE_DATE, MIN_HOSTING), '20991231') end_date from vtailratio_tmp where AREA_FLAG in ('0','1')) ) m, (select case when substr({"origin" :"param", "field" :"dateStart","where" :"%s"}, 1, 4)=substr({"origin" :"param", "field" :"dateEnd","where" :"%s"}, 1, 4) and mod(substr({"origin" :"param", "field" :"dateEnd","where" :"%s"}, 1, 4),4)=0 then '366' else '365' end YearDays from dual) year where distributor_code = hzA.distributor_code and fund_code = hzA.fund_code and hzA.HOLD_DATE >= ENABLE_DATE and hzA.HOLD_DATE < end_date GROUP BY AREA_FLAG),0)) fee, 0 TAIL_COMMISSION_RATIO, sum(nvl(income,0)) income, avg(BALANCE) avgbalance, avg(SHARES) avgshares from( SELECT A.HOLD_DATE, A.distributor_code, A.fund_code, 'A' share_class, A.TRANSACTION_CFM_DATE, decode(tfa.OPERATE_WAY, '0',a.balance, '1',nvl(A.balance, 0) - nvl(A.REINVEST_BALANCE, 0), '2',nvl(A.ORI_HOLD_BALANCE, 0), '3',nvl(A.ORI_HOLD_BALANCE, 0) - nvl(A.ORI_REINVEST_BALANCE, 0)) BALANCE, decode(tfa.OPERATE_WAY, '0',a.shares, '1',nvl(A.shares, 0) - nvl(A.REINVEST_SHARE, 0), '2',nvl(A.shares, 0), '3',nvl(A.shares, 0) - nvl(A.REINVEST_SHARE, 0)) SHARES, A.income ,D.NAV NAV, nvl(tfa.YEAR_DAY,0) YEAR_DAY FROM( select a.distributor_code, a.fund_code, 'A' share_class, a.TRANSACTION_CFM_DATE, a.HOLD_DATE, a.HOLD_RATIO, nvl(a.income, 0) income, nvl(a.REINVEST_SHARE, 0) REINVEST_SHARE, nvl(a.REINVEST_BALANCE, 0) REINVEST_BALANCE, nvl(a.ORI_HOLD_BALANCE, 0) ORI_HOLD_BALANCE, NVL(A.ORI_REINVEST_BALANCE, 0) ORI_REINVEST_BALANCE, case when b.ACC_INCOME_TO_SHARE_FLAG = '0' or /** #TACode || **/ '94'||a.distributor_code = '48002' then nvl(a.HOLD_BALANCE, 0) else nvl(a.HOLD_BALANCE, 0) + nvl(a.income, 0) end balance, case when b.ACC_INCOME_TO_SHARE_FLAG = '0' or /** #TACode || **/ '94'||a.distributor_code = '48002' then nvl(a.HOLD_SHARE, 0) else nvl(a.HOLD_SHARE, 0) + nvl(a.income, 0) end shares from FUND_SALE_STAT a,fund_info b WHERE a.INDIVIDUAL_OR_INSTITUTION = '*' and A.TRANSACTION_CFM_DATE >= {"origin" :"param", "field" :"dateStart","where" :"%s"} and a.TRANSACTION_CFM_DATE <= {"origin" :"param", "field" :"dateEnd","where" :"%s"} and a.fund_code = b.fund_code ) A, vtailratio_tmp tfa , NET_VALUE D where A.fund_code = tfa.fund_code AND A.distributor_code = tfa.distributor_code AND A.fund_code = D.fund_code AND D.TRANSACTION_CFM_DATE = (select min(fd.TRANSACTION_CFM_DATE) from NET_VALUE fd where fd.TRANSACTION_CFM_DATE >= a.TRANSACTION_CFM_DATE and fd.fund_code = a.fund_code ) and not exists(select * from GRADING_FUND_PLAN tsc where tsc.MAIN_FUND_CODE = A.fund_code and tsc.SECTION_FUND_CODE = '******') and a.transaction_cfm_date >= {"origin" :"param", "field" :"dateStart","where" :"%s"} and a.transaction_cfm_date <= {"origin" :"param", "field" :"dateEnd","where" :"%s"} {"origin" :"param", "field":"agencyCodeList", "where" :" and a.distributor_code in (%s)"} {"origin" :"param", "field" :"fundCodeList", "where" :" and a.fund_code in (%s)"} /** and #WhereSql **/ ) hzA group by distributor_code,fund_code,share_class,TRANSACTION_CFM_DATE ) where GetSysValueRX('System', 'TailSegment', '0') = '1' AND GetSysValueRX('System', 'TailMode', '1') = '1' union all select A.distributor_code, A.fund_code, A.TRANSACTION_CFM_DATE,'A' share_class, 0 BALANCE, 0 SHARES, round(nvl(A.TRANSFER_FEE,0)*tfb.distributor_ratio,2) fee, 0 TAIL_COMMISSION_RATIO, 0 income, 0 avgbalance, 0 avgshares from( select t.* from( select * from trade_confirm union all select * from TRADE_CONFIRM_LOG ) t ) A,fee_belong tfb where A.fund_code = tfb.fund_code and A.distributor_code = tfb.distributor_code and tfb.fee_type = '31' and A.CHECK_RESULT = '1' and A.BUSINESS_CODE = '124' and A.TRANSFER_FEE>0 and GetSysValueRX('Report','TailsIncludeProfit','0')='1' /** and #WhereSql **/ and a.transaction_cfm_date >= {"origin" :"param", "field" :"dateStart","where" :"%s"} and a.transaction_cfm_date <= {"origin" :"param", "field" :"dateEnd","where" :"%s"} {"origin" :"param", "field":"agencyCodeList", "where" :" and a.distributor_code in (%s)"} {"origin" :"param", "field" :"fundCodeList", "where" :" and a.fund_code in (%s)"} ) group by distributor_code,fund_code,TRANSACTION_CFM_DATE )a, (select fund_code,distributor_code, min_tail_fare from( select fund_code,distributor_code,nvl(min_tail_fare,0) min_tail_fare, ROW_NUMBER() OVER(PARTITION BY fund_code , distributor_code ORDER BY fund_code DESC,distributor_code DESC) RANK from vtailratio_tmp) tfa where RANK=1 ) tfa,fund_info fi,distributor_info di where a.fund_code = tfa.fund_code and a.fund_code = fi.fund_code and a.distributor_code = di.distributor_code and a.distributor_code = tfa.distributor_code group by a.distributor_code,di.distributor_name,a.fund_code,fi.fund_name,tfa.min_tail_fare ,TAIL_COMMISSION_RATIO )order by fundcode,distributor_code给这段sql划分层次使人更容易理解
07-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值