- 浏览: 276878 次
文章分类
最新评论
-
guji528:
oracle的统计函数真的很强大
Oracle 使用LAG和LEAD函数统计 -
haiyangyiba:
受教了
No Dialect mapping for JDBC type: 3 -
elvishehai:
能不能给个完整点的例子呀,我一直都没有试成功过,
简单的使用jackson的annotation -
miaoyue:
如果我想把name属性转成注释之后,之前的注释还在怎么做?
PowerDesigner 中将Comment(注释)及Name(名称)内容互相COPY的VBS代码 -
ianl_zt:
以上方法只适合在hibernate2中使用,现在hiberna ...
Hibernate的批量更新和删除
分析函数是Oracle从8.1.6开始引入的一个新的概念,为我们分析数据提供了一种简单高效的处理方式。在分析函数出现以前,我们必须使用自联查询,子查询或者内联视图,甚至复杂的存储过程实现的语句,现在只要一条简单的SQL语句就可以实现了,而且在执行效率方面也有相当大的提高。下面我将针对分析函数做一些具体的说明。
分析函数的一般格式是函数名(参数列表) over ([partition by 字段名或表达式] [order by 字段名或表达式]),其中over()部分称为开窗函数,它是可以选填的。
开窗函数指定了分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变化而变化,举例如下:
over(order by salary) 按照salary排序进行累计,order by是个默认的开窗函数
over(partition by deptno)按照部门分区
over(order by salary range between 50 preceding and 150 following)
每行对应的数据窗口是之前行幅度值不超过50,之后行幅度值不超过150
over(order by salary rows between 50 preceding and 150 following)
每行对应的数据窗口是之前50行,之后150行
over(order by salary rows between unbounded preceding and unbounded following)
每行对应的数据窗口是从第一行到最后一行,等效:
over(order by salary range between unbounded preceding and unbounded following)
分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是对于每个组返回多行,而聚合函数对于每个组只返回一行。
许多分析函数同时也是聚合函数,比如sum()函数,这样使用就是聚合函数。
SQL> select department_id,sum(salary) sum_salary from employees group by department_id;
而这样使用就是分析函数。
SQL> select distinct department_id,sum(salary) over(partition by department_id) sum_salary from employees ;
它们得出的结果是相同的,都是:
DEPARTMENT_ID SUM_SALARY
------------- ----------
10 4400
20 19000
30 24900
40 6500
50 156400
60 28800
70 10000
80 304500
90 58000
100 51600
110 20300
7000
已选择12行。
请注意,这里我们用到了distinct 关键字,如果不用distinct,第2个查询将返回107行数据,即employees表的每行记录都将返回一行sum_salary,因为不用distinct的含义是:针对每个雇员计算他/她所在的部门的薪金总数。
在这个例子中,聚合函数是更好的选择,但在另外一些情形下,我们更应该使用分析函数。
下面通过几个实例来介绍部分分析函数的用途。
问题1:求出每个省工业企业利润总额最多的前10名。
利用我们传统的聚合函数max可以方便地取出利润总额最多的一家,但是取出多家就无能为力了,同样,如果不分组我们可以通过排序取出任何一个省利润总额最多的前10名,但无法实现对多个省的分组。而采用rank聚合函数,可以方便地实现我们的要求。
完整的语句如下:
select * from
(select substr(z01_04,1,2) 地区码,
DENSE_RANK() OVER (PARTITION BY substr(z01_04,1,2) order by b04_50 desc) 名次, b04_50 "利润总额"
from cj604,cj601 where b04_50>0 and cj601.uuid=cj604.uuid ) where 名次<=10;
我们在开窗函数中使用地区码作为分组标志,并按照利润总额倒序排列。
结果如下(数据为模拟数据,以下同)
地区 名次 利润总额
---- ---------- ----------
31 1 963799
31 2 229643
...
31 9 135917
31 10 125245
32 1 349940
32 2 300587
...
注意:RANK()函数有3组,分别是rank, dense_rank, row_number,它们的区别是:
rank如果出现两个相同的数据,那么后面的数据就会直接跳过这个排名,比如:当第2名和第3名的利润相同时,rank的结果是1,2,2,4;而dense_rank则不会跳过这个排名,结果是1,2,2,3;而row_number哪怕是两个数据完全相同,排名也会不一样,结果是1,2,3,4
问题2:求出按登记注册类型分组的职工人数和销售额占总体的比重
分析函数ratio_to_report专门用来解决个体占总体的比重一类的问题。
语句
select d.*,round((ratio_to_report(职工人数) over())*100,1) as 人数百分比,
round((ratio_to_report(销售额) over())*100,1) as 销售额百分比
from
(select c.code 代码 , substr(b.reg_type,1,10) 登记注册类型, 职工人数, 销售额 from
(select substr(z01_08,1,1)||'00' code, sum(z01_171_01) 职工人数,sum(b03_01) 销售额
from cj603 c,cj601
j where c.uuid=j.uuid group by substr(z01_08,1,1)
)c, djzclx b where c.code=b.reg_code
)d;
可以得出下面的结果:
代码 登记注册类型 职工人数 销售额 人数百分比 销售额百分比
---- -------------------- ---------- ---------- ---------- ------------
100 内资企业 8510509 3002627283 63 56.2
200 港、澳、台商投资企业 2066175 746728306 15.3 14
300 外商投资企业 2936984 1597046896 21.7 29.9
其中内层的子查询语句
select substr(z01_08,1,1)||'00' code, sum(z01_171_01) 职工人数,sum(b03_01) 销售额
from cj603 c,cj601 j where c.uuid=j.uuid group by substr(z01_08,1,1)
获得如下的结果
CODE 职工人数 销售额
---- ---------- ----------
100 8510509 3002627283
200 2066175 746728306
300 2936984 1597046896
外层查询中ratio_to_report函数自动对结果集中的职工人数和销售额计算比重。
问题3 求按行业中类划分的大中小型企业个数
case语句不是分析函数,但它在统计汇总中的作用非常重要,可以用来设定复杂的分组条件。
以下是统计上工业大中小型企业划分标准。
指标名称 |
计量单位 |
大型 |
中型 |
小型 |
从业人员数 |
人 |
2000及以上且 |
300-2000以下 |
300以下或 |
销售收入 |
万元 |
30000及以上且 |
3000-30000以下 |
3000以下或 |
资产合计 |
万元 |
40000及以上 |
4000-40000以下 |
4000以下 |
请注意下面这个说明:大型和中型企业须同时满足所列各项条件的下限指标,否则下划一档。
比如某企业虽然从业人员数和销售收入符合大型企业的要求,但资产合计30000万元,不满足大型企业的要求,只能划归中型企业。实际上,中型企业单位数=企业单位总数-大型企业单位数-小型企业单位数。
因此,用b04_71<2000 and b04_71>=300 and b04_29>=30000 and b04_29<300000 and b04_16>=40000 and b04_16<400000的写法来表述中型标准是错误的。
正确写法应该是:
not(b04_71>=2000 and b04_29>=300000 and b04_16>=400000) and not(b04_71<300 or b04_29<30000 or b04_16<40000),当然前提是这3个字段没有空值null。
完整的SQL语句如下:
select code 代码 , substr(INDUSTRY_NAME,1,10) 行业名称, c.* from
(
select substr(z01_064,1,2) as code ,count(*) as TOL,
count(case when b04_71>=2000 and b04_29>=300000 and b04_16>=400000 then 1 else null end) as big,
count(case when not(b04_71>=2000 and b04_29>=300000 and b04_16>=400000)
and not(b04_71<300 or b04_29<30000 or b04_16<40000) then 1 else null end) as mid,
count(case when b04_71<300 or b04_29<30000 or b04_16<40000 then 1 else null end) as small
from cj604 a,cj601 b where a.uuid=b.uuid group by substr(z01_064,1,2)
)c, industry b where c.code=b.INDUSTRY_CODE
输出结果如下:
代码 行业名称 CODE TOL BIG MID SMALL
---- ------------------ ---- ---------- ---------- ---------- ----------
06 煤炭开采和洗选业 06 9 1 2 6
07 石油和天然气开采业 07 3 1 0 2
08 黑色金属矿采选业 08 13 1 3 8
13 农副食品加工业 13 1342 2 48 1269
14 食品制造业 14 784 3 66 691
15 饮料制造业 15 385 0 31 331
...
问题4 求按地区划分的3种登记注册类型的营业利润率
decode函数不是分析函数,但它在统计汇总中的作用非常重要,它的格式是:
decode(字段名或表达式,比较值1,返回值1, [比较值2,返回值2,...] 默认返回值),它的作用是当字段或表达式的值等于比较值1时,就得出返回值1,当字段或表达式的值等于比较值2时,就得出返回值2,以此类推,如果都不符合,就返回默认返回值。其中从比较值2开始的参数对可以不提供。
语句
select substr(name,1,4) 地区名称, c.*
from(select 地区代码,
decode(注册类型码,'1',营业利润率,null) A1,
decode(注册类型码,'2',营业利润率,null) A2,
decode(注册类型码,'3',营业利润率,null) A3
from(
select
substr(z01_04,1,2) 地区代码,substr(z01_08,1,1) 注册类型码,
round(sum(b04_45)/sum(b04_29)*100,2) 营业利润率
from cj601 a,cj604 b where a.uuid=b.uuid
group by substr(z01_04,1,2),substr(z01_08,1,1)
)
)c,dq
where 地区代码=dq.code;
得出如下结果。
地区名称 地区 A1 A2 A3
-------- ---- ------ ------ ------
上海 31 6.74
上海 31 5.30
上海 31 6.37
江苏 32 3.94
江苏 32 4.85
江苏 32 4.32
浙江 33 4.55
浙江 33 5.25
浙江 33 5.76
因为decode函数只针对一行内的数据进行处理,这样的结果并不符合要求,我们需要在第二层查询语句的外面再加一层按地区代码的分组汇总,完整写法如下:
select substr(name,1,4) 地区名称, c.*
from(
select 地区代码,SUM(A1) A1,SUM(A2) A2,SUM(A3) A3 from(
select 地区代码,
decode(注册类型码,'1',营业利润率,null) A1,
decode(注册类型码,'2',营业利润率,null) A2,
decode(注册类型码,'3',营业利润率,null) A3
from(
select
substr(z01_04,1,2) 地区代码,substr(z01_08,1,1) 注册类型码,
round(sum(b04_45)/sum(b04_29)*100,2) 营业利润率
from cj601 a,cj604 b where a.uuid=b.uuid
group by substr(z01_04,1,2),substr(z01_08,1,1)
)
)group by 地区代码 )c,dq
where 地区代码=dq.code;
这样就得到了正确的结果:
地区名称 地区 A1 A2 A3
------- ---- ------ ------ ------
上海 31 6.74 5.30 6.37
江苏 32 3.94 4.85 4.32
浙江 33 4.55 5.25 5.76
同样的问题我们也可以通过lead分析函数来完成。
select substr(name,1,4) 地区名称, 地区代码, A1,A2,A3
from(
select * from(
select 地区代码,
lead(营业利润率, 0) over(partition by 地区代码 order by 注册类型码) A1,
lead(营业利润率, 1) over(partition by 地区代码 order by 注册类型码) A2,
lead(营业利润率, 2) over(partition by 地区代码 order by 注册类型码) A3,
row_number( ) over(partition by 地区代码 order by 注册类型码) rn
from(
select
substr(z01_04,1,2) 地区代码,substr(z01_08,1,1) 注册类型码,
round(sum(b04_45)/sum(b04_29)*100,2) 营业利润率
from cj601 a,cj604 b where a.uuid=b.uuid
group by substr(z01_04,1,2),substr(z01_08,1,1)
))where rn=1
)c,dq
where 地区代码=dq.code;
lead函数的第一个参数是我们关心的值,第2个参数是偏移量n,对本例就是下n种注册类型码。
之所以要限定rn=1,还是因为分析函数对每一行都返回分组值,而我们关心的是注册类型为1的那一行。
利用lag和lead函数,我们可以在同一行中显示前n行的数据,也可以显示后n行的数据。
如果本例改用lag函数实现,代码如下:
注意过滤条件rn=3以及lag函数第2个参数的变化,我们把第3行作为当前行,取出它前面的2行。
select substr(name,1,4) 地区名称, 地区代码, A1,A2,A3
from(
select * from(
select 地区代码,
lag(营业利润率, 2) over(partition by 地区代码 order by 注册类型码) A1,
lag(营业利润率, 1) over(partition by 地区代码 order by 注册类型码) A2,
lag(营业利润率, 0) over(partition by 地区代码 order by 注册类型码) A3,
row_number( ) over(partition by 地区代码 order by 注册类型码) rn
from(
select
substr(z01_04,1,2) 地区代码,substr(z01_08,1,1) 注册类型码,
round(sum(b04_45)/sum(b04_29)*100,2) 营业利润率
from cj601 a,cj604 b where a.uuid=b.uuid
group by substr(z01_04,1,2),substr(z01_08,1,1)
))where rn=3
)c,dq
where 地区代码=dq.code;
这种方法比前一种方法利用sum分组汇总的好处是对字符类型和其他非数值类型字段都可以采用。
发表评论
-
30个Oracle语句优化规则详解
2009-06-18 10:35 31101.选用适合的Oracle优化 ... -
30个Oracle语句优化规则详解
2009-06-18 10:35 28641.选用适合的Oracle优化 ... -
Oracle RBO、CBO简介
2009-06-18 10:34 4159Rule Based Optimizer(RBO)基于规则Co ... -
索引什么时候不工作
2009-06-18 10:33 3672首先要声明两个知识点: (1)RBO& ... -
Oracle的SQLPLUS命令使用集合
2009-06-18 10:29 48481. 执行一个SQL脚本文件 ... -
Oracle DBA在新环境下必须了解的事情
2009-06-18 10:28 1863面对一个全新的环境,作为一个Oracle DBA,首先应 ... -
三招让Oracle表列管理更加简单
2009-06-18 10:27 3017Oracle数据库是目前为止最复杂的一个数据库之一。也正是这种 ... -
oracle lead 使用实践
2009-06-18 10:26 5593oracle 统计分析函数 lead 语法结构: ... -
oracle count计数的优化
2009-06-18 10:25 9575在9i,我们知道count(*)的时候,如果表上有pk,那co ... -
Oracle HINT的常见用法
2009-06-18 10:23 2924提示(hint)从Oracle7中引入,目的是弥补基于成本优化 ... -
利用Oracle内置分析函数进行高效统计汇总(2)
2009-06-18 10:22 2227问题5 求按登记注册类 ... -
奇怪的ora-01722错误
2009-06-18 10:12 3072一个和子查询,视图有 ...
相关推荐
### Oracle内置SQL函数-分类整理大全 #### F.1 字符函数——返回字符值 **1.1.1 CHR** - **语法**: `CHR(x)` - **功能**: 返回在数据库字符集中与`x`拥有等价数值的字符。`CHR`和`ASCII`是一对反函数,即经过`CHR...
本文将深入探讨Oracle内置的SQL函数,这些函数极大地丰富了数据查询、处理和分析的能力。 一、数学函数 Oracle提供了丰富的数学函数,如ROUND、TRUNC、MOD、SQRT等。ROUND用于四舍五入,例如ROUND(123.456, 2)将...
Oracle数据库系统是世界上最广泛使用的数据库管理...通过熟练掌握这些Oracle内置的SQL函数,开发者可以更高效地处理和管理数据库中的数据。在sqlplus环境中,可以编写脚本文件并执行,实现自动化操作,提高工作效率。
Oracle分析函数是数据库查询中的重要工具,主要用于处理复杂的聚合和排序操作,特别是在OLAP(在线分析处理)系统中,它们能够高效地进行数据汇总和分析。分析函数与聚合函数(如SUM, AVG, COUNT等)有所不同,聚合...
### Oracle 最全函数大全 #### 一、总体介绍 ...分析函数特别适合处理复杂的数据分析任务,而聚合函数则是进行统计分析的基础。掌握这些函数能够帮助开发人员更加高效地管理和操作数据库中的数据。
Oracle数据库系统是世界上最广泛使用的数据库管理系统之一,其强大的功能和高效的数据处理能力离不开丰富的内置函数。这些函数在SQL查询、数据处理、计算以及各种复杂的业务逻辑中起着至关重要的作用。下面将详细...
5. "oracle函数介绍(6) 著名函数之分析函数.doc"和"oracle函数介绍(7) 非著名函数之分析函数.doc"会进一步详细讨论这些高级函数,可能包括窗口函数的用法和实例。 6. "oracle函数介绍(8) 综述.doc"应该是对前面所有...
6. **分析函数**:分析函数在处理大量数据时非常有用,如`RANK`、`DENSE_RANK`和`ROW_NUMBER`用于生成行序号,`LEAD`和`LAG`可以访问当前行的前一行或后一行数据,`FIRST_VALUE`和`LAST_VALUE`则用于获取分组内第一...
**聚组函数**如`COUNT`、`SUM`、`AVG`、`MAX`和`MIN`用于对一组数据进行统计汇总。它们常在SQL查询的`GROUP BY`语句中使用,帮助我们快速获取每个分组的计数、总和、平均值、最大值和最小值。 **分析函数**如`RANK`...
Oracle数据库是世界上最广泛使用的数据库系统之一,其强大的功能和丰富的内置函数使得数据处理变得高效而灵活。本篇文章将深入探讨“Oracle常见函数集锦”,主要关注在SQL查询中常用的Oracle函数,这些函数对于数据...
Oracle数据库系统是世界上最广泛使用的数据库管理系统之一,它提供了丰富的内置函数来支持各种数据处理和查询需求。本资源“oracle函数大全(chm格式分类显示)”详细介绍了Oracle中的主要函数类别,帮助用户更好地...
本文档将详细介绍一系列Oracle函数及其应用场景,帮助用户更好地理解和掌握如何利用这些函数进行高效的数据处理。 #### 二、字符串函数 1. **ASCII**: 返回字符的ASCII码。 - 示例:`ASCII('A')` 返回65。 2. **...
7. **分组和分析函数**: - `GROUP BY`:根据一个或多个列对结果集进行分组。 - `ROLLUP`:创建分组的多级汇总。 - `CUBE`:生成所有可能的子集组合。 8. **连接查询相关函数**: - `JOIN`:将两个或更多表的...
在数据分析中,`COUNT()`、`SUM()`、`AVG()`、`MAX()`和`MIN()`等聚合函数用于对一组值进行统计汇总。它们在报表和数据分析中扮演着重要角色。 七、分组和排序函数 `GROUP BY`语句配合聚合函数用于对数据进行分组,...
9. 分组和分析函数:如GROUP BY、ROLLUP、CUBE和RANK等,用于数据的分组汇总和复杂分析,是大数据处理和OLAP操作的关键。 10. 连接函数:如CONNECT_BY_ROOT和START_WITH,用于构建复杂的树状查询,处理层次结构数据...
6. **分组和分析函数**: - `GROUP BY`: 用于对数据进行分组。 - `ROLLUP()`: 生成多级汇总。 - `CUBE()`: 生成所有可能的子集组合。 - `RANK()`, `DENSE_RANK()`, `ROW_NUMBER()`: 用于排序和生成行号。 7. **...
在Oracle数据库中,SQL函数被广泛应用于各种数据处理需求,例如数据筛选、计算汇总、格式化等。本文将详细介绍Oracle中的常见函数及其应用场景,帮助用户更好地理解和掌握这些实用工具。 #### 一、基本统计函数 1....