分组求和SQL示例

   

1、ROLLUP和CUBE函数,自动汇总数据

select * from test_tbl的数据这样的
     col_a col_b col_c
     ---- ----- -----
     1     
b1   12
     1     
b1   2
     1     
b2   31
     2     
b2   7
     2     
b3   42
     2     
b3   1
     2     
b3   3
     如果按A、B列进行汇总C列,用一般的方法是这样:

select col_a,col_b,sum(col_c) from
test_tbl group by col_a,col_b 结果如下
     col_a col_b sum(col_c)
     ---- ----- --------
     1     
b1    14
     1     
b2    31
     2     
b2    7
     2     
b3    46
    
但是如果这时候还想按A列汇总且要C列的合计数,那就要再用两个SQL来嵌套,很麻烦,不过用

rollup就简单多了:
     select nvl(col_a,‘合计‘)
col_a,nvl(col_b,decode(col_a,null,‘‘,‘小计‘||col_a))

col_b,sum(col_c)
     from test_tbl group by
rollup(col_a,col_b),结果如下
     col_a col_b sum(col_c)
     ---- ----- --------
     1     
b1     14
     1     
b2     31
     1    小计1  
45
     2     
b2     7
     2     
b3     46
     2    小计2  
53
     合计 98
    
结果集刚好是先按A和B汇总,然后是按A汇总,最后是全部汇总这时候如果再要按B列汇总,怎么办

呢?又要用SQL嵌套吗?不是的,如果有这要求的话,改用cube函数就OK啦

select
nvl(col_a,decode(col_b,null,‘合计‘,‘小计‘||col_b))
col_a,nvl(col_b,decode

(col_a,null,‘‘,‘小计‘||col_a)) col_b,sum(col_c)
     from test_tbl group by cube(col_a,col_b)
结果如下
     col_a col_b sum(col_c)
     ---- ----- --------
     1     
b1     14
     1     
b2     31
     1    小计1  
45
     2     
b2     7
     2     
b3     46
     2    小计2  
53
    小计b1  b1    14
    小计b2  b2    38
    小计b3  b3    46
    合计 98
    
跟刚才rollup函数得到的结果集有点不一样,那就是多了些按B列的汇总行。

2、LAG和LEAD函数,自动链接上/下行记录值

SQL> desc
test_tbl
     Name Type
     ----- ------
     COL_K NUMBER
     现在按顺序的往这个test_tbl表中插入一系列数据,下面是SQL:
     insert into test_tbl values(1)
     insert into test_tbl values(2)
     insert into test_tbl values(4)
     insert into test_tbl values(5)
     insert into test_tbl values(8)
     insert into test_tbl values(9)
     insert into test_tbl values(11)
     insert into test_tbl values(12)
     insert into test_tbl values(13)
     ........
    
数据插完后,要检查插入的数据中,从最小数到最大数之间有那些数是没被插入表,找出这些数的

前一个和后一个数?如这个例里从1到13当中有目字3、6、7、10没被插入表中,这些数的前一个和后一

个分别是2和4、5和8、9和11,即
     PREV_VAL NEXT_VAL
     ---------- ----------
     2 4
     5 8
     9 11
    
如果不用分析函数要得到这后结果集那真不敢想象是怎么样的一段SQL,但用LAG分析函数那就简单

了,这样写就OK
     select prev_val,next_val from(
     select col_k next_val,lag(col_k,1,0) over
(order by col_k) prev_val from test_tbl
     ) where
next_val-prev_val>1
     对于LEAD函数是一样的,只不过它是往后链接而已。

3、RANK和DENSE_RANK函数,对数据进行排名

测试表是这样的select *from
test_tbl结集如下
     COL_A COL_B
     ---------- ----------
     A 242
     A 233
     B 154
     C 287
     C 76
     D 66
     E 154
     F 154
     G 212
     G 43
     按A列来统计B列的值,用一般的SQL是这样select col_a,
sum(col_b) from test_tbl group by

col_a order by 2 desc 结果是这样
     COL_A SUM(COL_B)
     ---------- ----------
     A 475
     C 363
     G 255
     B 154
     F 154
     E 154
     D 66
    
从这个数据集可以看出A是最大的,C是第二大的,当数据多时就不知道谁是排第几了,这时用

DENSE_RANK可以达到这目的
     select col_a,sum(col_b),dense_rank() over
(order by sum(col_b) desc) ranks from

test_tbl group by col_a 结果如下
     COL_A SUM(COL_B) RANKS
     ---------- ---------- ----------
     A 475 1
     C 363 2
     G 255 3
     B 154 4
     F 154 4
     E 154 4
     D 66 5
     这个数据集把每个值都排了名次,可以直接看得出,相同值的名次是相同的。
    
用RANK跟DENSE_RANK差不多,不过就是当出现在名次相同时,下一个名次会跳跃
     select col_a,sum(col_b),rank() over (order
by sum(col_b) desc ) ranks from test_tbl

group by col_a 结果如下
     COL_A SUM(COL_B) RANKS
     ---------- ---------- ----------
     A 475 1
     C 363 2
     G 255 3
     B 154 4
     F 154 4
     E 154 4
     D 66 7
     可以看到名次从4跳跃到7,就是因为名次4重复出现了两次

实际应用中可能会比这些例子要复杂多点,可能会先对表的数据分组,然后再用分析,如
     select *from test_tbl的结果是这样的
     COL_G COL_A COL_B
     ---------- ---------- ----------
     G1 A 242
     G1 A 233
     G2 C 287
     G2 C 76
     G2 D 66
     G2 E 154
     G3 F 154
     G3 G 212
     G3 G 43
     G2 B 154
    
对这个数据集按G和A列汇总B列进行排名,就要先对表按G列进行分组,然后再按A列汇总B列值进行

排名
     select col_g,col_a,sum(col_b),dense_rank()
over (partition by col_g order by sum

(col_b) desc ) ranks
     from test_tbl
     group by col_g,col_a这个SQL加了partition
by先按G列分组,结果如下
     COL_G COL_A SUM(COL_B) RANKS
     ---------- ---------- ----------
----------
     G1 A 475 1
     G2 C 363 1
     G2 B 154 2
     G2 E 154 2
     G2 D 66 3
     G3 G 255 1
     G3 F 154 2
     可以看到名次都是在G列的组别发生变化时,就会重新开始新排列
;

时间: 2024-10-13 02:00:05

分组求和SQL示例的相关文章

DataTable分组求和【UP,UP,UP】

来来来,大家注意了,DataTable分组求和的简单方式 '定义一个临时变量,用于判断某个分组是否已经求过和dim temp=""'求和的值dim sumValue'循环DataTablefor each dr in 网格部件1.DataTable.Rows        '根据长度判当前这条数据所属的分组是否已经求过和(在分组名称前后加上“|”,是为了避免:“是”“不是”这样的分组,这养的分组不加符号就判断不到)        if(Len(Replace(temp,"|&

java8 stream自定义分组求和并排序

public static void main(String[] args) { List<GroupDetailDTO> list = new ArrayList<>(); GroupDetailDTO dto1 = new GroupDetailDTO(); dto1.setHeadsetId(1); dto1.setTime("2020-01-03"); dto1.setActConcreteTime("a"); dto1.setPla

SQL技巧之分组求和

这是CSDN问答里面有人提出的一道问题,题目如下. 表格如下: 得出结果如下: 求精简的SQL语句. SQL查询语句: with a as( select rank() over (partition by 商店 order by 商店,sum(价钱) desc) as rowid, 商店,sum(价钱) as 价钱和,备注 from 产品 group by 备注,商店), b as( select 商店,价钱和,备注 from a where rowid = 1), c as( select

[0101]分组求和 &nbsp; 、{}匹配 与 二进制数 记录

****************************** **       更正               ** **    1. 算式求和           ** **    2. 花括号             ** **    3. 二进制1个数        ** ****************************** #include <stdio.h> #include <stdlib.h> #define N  5   //  计算到1/5 int ma

mysql 行转列,对列的分组求和,对行求和

CREATE TABLE students( id INT PRIMARY KEY, NAME VARCHAR(11)); CREATE TABLE courses( id INT PRIMARY KEY, NAME VARCHAR(11)); CREATE TABLE scores( sid INT, cid INT, score INT, RIMARY KEY (sid,cid)); 3表关联查询: SELECT st.id,st.name,c.NAME course,sc.score FR

【MyBatis】动态SQL示例

[MyBatis]配置文件示例 [MyBatis]映射文件示例 DAO文件 EmployeeMapperDynamicSQL.java package com.atguigu.mybatis.dao; import java.util.List; import org.apache.ibatis.annotations.Param; import com.atguigu.mybatis.bean.Employee; public interface EmployeeMapperDynamicSQ

Java批量将文件中的段落替换成空格,根据指定分隔符换行(SQL示例)

我的需求是SQL文件中有成千的类似数据,我要将它们进行转换格式,如下图 第一步:将字符段楼替换,使用word排版 把数据拷贝到word中,使用特殊字符替换 点击全部替换,替换之后如下图,这时候它是一串很长的字符串 第二步:编写Java替换程序 在代码中num是分割段,到第16个字符时候换行 public class Demo { public static void main(String[] args) { String s = "'133','153','180','181','189','

集算器实现几种常见内存分组的代码示例

集算器可以很方便地实现常见的几种内存分组,比如等值分组.对位分组.枚举分组,下面用相应的例子来说明. 等值分组 等值分组的分组依据是本数据集的字段(或字段派生的计算列),每个组都是原数据集的子集. 例子描述:将销售订单按照订单年份进行分组. 数据描述:订单数据如下: 上述数据集(序表)可以从数据库或文件读入,比如: A1=file("E:/sales.txt")[email protected]() 集算器代码 A2=A1.group(year(OrderDate)) 计算结果 代码解

通过存储过程进行分页查询的SQL示例

--创建人:zengfanlong --创建时间:2014-7-28 10:51:15 --说明:根据公司简写代码获取当前待同步的气瓶档案数据(分页获取) ALTER PROCEDURE [UP_GasBottles_GetSyncData_ByPage] ( @CompanyAbbrCode NVARCHAR(255) = '' , @LatastRowVersion_BigInt BIGINT , @CurrentMaxRowVersion_BigInt BIGINT , @StartPag