数据库版本:oralce  11g

表名WM_TD_WATER_DAILY 结构如下,我把没用到的字段隐藏了,全放出来不太好哈.

MONITOR_ID为BI_TB_MONITOR_BI的ID ,用于关联站点名称(SHORT_NAME).

业务需求 :现有日水量表,每条数据记录着一天的用水量,bi_tb_monitor_bi中有一下九个站点

全部SQL如下,下面有SQL分解,看起来能清晰很多

SELECT MON, CASEWHEN MON IS NULL AND DATETIME IS NULL THEN'累计水量'WHEN MON IS NOT NULL AND DATETIME IS NULL THEN'小计'ELSECASEWHEN INSTR(DATETIME, '1旬') > 0 THENREPLACE(DATETIME, '1旬', '上旬')WHEN INSTR(DATETIME, '2旬') > 0 THENREPLACE(DATETIME, '2旬', '中旬')WHEN INSTR(DATETIME, '3旬') > 0 THENREPLACE(DATETIME, '3旬', '下旬')ENDEND DATETIME,SUM(NVL(车逻洞, 0)) 车逻洞,SUM(NVL(车逻闸, 0)) 车逻闸,SUM(NVL(车逻, 0)) 车逻,SUM(NVL(南关, 0)) 南关,SUM(NVL(头闸, 0)) 头闸,SUM(NVL(周山洞, 0)) 周山洞,SUM(NVL(界首小闸, 0)) 界首小闸,SUM(NVL(子英闸, 0)) 子英闸,SUM(NVL(周山, 0)) 周山,SUM(NVL(车逻洞, 0)) + SUM(NVL(车逻闸, 0)) + SUM(NVL(南关, 0)) +SUM(NVL(头闸, 0)) + SUM(NVL(周山洞, 0)) + SUM(NVL(界首小闸, 0)) +SUM(NVL(子英闸, 0)) + SUM(NVL(周山, 0)) 合计FROM (SELECT TO_CHAR(MONITOR_DATE, 'yyyy') YEAR,TO_CHAR(MONITOR_DATE, 'yyyy') || TO_CHAR(MONITOR_DATE, 'mm') MON,TO_CHAR(MONITOR_DATE, 'mm') || '月' ||DECODE(TRUNC((TO_CHAR(MONITOR_DATE, 'dd') - 1) / 10), 0, '1旬' ,1, '2旬', '3旬') DATETIME,SUM(车逻洞) / 10000 车逻洞,SUM(车逻闸) / 10000 车逻闸,SUM(车逻) / 10000 车逻,SUM(南关) / 10000 南关,SUM(头闸) / 10000 头闸,SUM(周山洞) / 10000 周山洞,SUM(界首小闸) / 10000 界首小闸,SUM(子英闸) / 10000 子英闸,SUM(周山) / 10000 周山FROM (SELECT B.SHORT_NAME, T.MONITOR_DATE, T.WATER_DAILYFROM WM_TD_WATER_DAILY TLEFT JOIN BI_TB_MONITOR_BI BON T.MONITOR_ID = B.IDWHERE T.REGION_ID = '6-100-018'AND T.MONITOR_DATE BETWEEN TO_DATE('2018-10', 'yyyy-MM') ANDTO_DATE('2018-12', 'yyyy-MM'))PIVOT(SUM(WATER_DAILY)FOR SHORT_NAME IN('车逻洞' 车逻洞,'车逻闸' 车逻闸,'车逻' 车逻,'南关' 南关,'头闸' 头闸,'周山洞' 周山洞,'界首小闸' 界首小闸,'子英闸' 子英闸,'周山' 周山))GROUP BY TO_CHAR(MONITOR_DATE, 'yyyy'),TO_CHAR(MONITOR_DATE, 'mm'),DECODE(TRUNC((TO_CHAR(MONITOR_DATE, 'dd') - 1) / 10),0,'1旬' ,1,'2旬','3旬')ORDER BY MON)GROUP BY ROLLUP(MON, DATETIME)

SQL分解

第一层SQL:

只做最基本的查询,并把条件都写好

 SELECT B.SHORT_NAME, T.MONITOR_DATE, T.WATER_DAILYFROM WM_TD_WATER_DAILY TLEFT JOIN BI_TB_MONITOR_BI BON T.MONITOR_ID = B.IDWHERE T.REGION_ID = '6-100-018'AND T.MONITOR_DATE BETWEEN TO_DATE('2018-10', 'yyyy-MM') ANDTO_DATE('2018-12', 'yyyy-MM')

查询结果如下(只插入了两个站点的数据<车逻洞>,<车逻闸>):

第二层SQL:

用decode(trunc((to_char(monitor_date,'dd')-1)/10),0,'1旬',1,'2旬','3旬') 把旬分组,

行转列用了 PIVOT (sum(water_daily) for short_name in ('车逻洞' 车逻洞, '车逻闸' 车逻闸,'车逻' 车逻,
 '南关' 南关,'头闸' 头闸,'周山洞' 周山洞,'界首小闸' 界首小闸,'子英闸' 子英闸,'周山' 周山))

每个sum后除以10000是业务需求

SELECT TO_CHAR(MONITOR_DATE, 'yyyy') YEAR,TO_CHAR(MONITOR_DATE, 'yyyy') || TO_CHAR(MONITOR_DATE, 'mm') MON,TO_CHAR(MONITOR_DATE, 'mm') || '月' ||DECODE(TRUNC((TO_CHAR(MONITOR_DATE,'dd') - 1) / 10), 0, '1旬' ,1, '2旬', '3旬')DATETIME,SUM(车逻洞) / 10000 车逻洞,SUM(车逻闸) / 10000 车逻闸,SUM(车逻) / 10000 车逻,SUM(南关) / 10000 南关,SUM(头闸) / 10000 头闸,SUM(周山洞) / 10000 周山洞,SUM(界首小闸) / 10000 界首小闸,SUM(子英闸) / 10000 子英闸,SUM(周山) / 10000 周山FROM (SELECT B.SHORT_NAME, T.MONITOR_DATE, T.WATER_DAILYFROM WM_TD_WATER_DAILY TLEFT JOIN BI_TB_MONITOR_BI BON T.MONITOR_ID = B.IDWHERE T.REGION_ID = '6-100-018'AND T.MONITOR_DATE BETWEEN TO_DATE('2018-10', 'yyyy-MM') ANDTO_DATE('2018-12', 'yyyy-MM'))PIVOT(SUM(WATER_DAILY)FOR SHORT_NAME IN('车逻洞' 车逻洞,'车逻闸' 车逻闸,'车逻' 车逻,'南关' 南关,'头闸' 头闸,'周山洞' 周山洞,'界首小闸' 界首小闸,'子英闸' 子英闸,'周山' 周山))GROUP BY TO_CHAR(MONITOR_DATE, 'yyyy'),TO_CHAR(MONITOR_DATE, 'mm'),DECODE(TRUNC((TO_CHAR(MONITOR_DATE, 'dd') - 1) / 10),0,'1旬' ,1,'2旬','3旬')ORDER BY MON

查询结果如下:

最后一层SQL:

用了 GROUP BY ROLLUP (MON,DATETIME)  按MON,DATETIME分组合计

SELECT CASEWHEN MON IS NULL AND DATETIME IS NULL THEN'累计水量'WHEN MON IS NOT NULL AND DATETIME IS NULL THEN'小计'ELSECASEWHEN INSTR(DATETIME, '1旬') > 0 THENREPLACE(DATETIME, '1旬', '上旬')WHEN INSTR(DATETIME, '2旬') > 0 THENREPLACE(DATETIME, '2旬', '中旬')WHEN INSTR(DATETIME, '3旬') > 0 THENREPLACE(DATETIME, '3旬', '下旬')ENDEND DATETIME,SUM(NVL(车逻洞, 0)) 车逻洞,SUM(NVL(车逻闸, 0)) 车逻闸,SUM(NVL(车逻, 0)) 车逻,SUM(NVL(南关, 0)) 南关,SUM(NVL(头闸, 0)) 头闸,SUM(NVL(周山洞, 0)) 周山洞,SUM(NVL(界首小闸, 0)) 界首小闸,SUM(NVL(子英闸, 0)) 子英闸,SUM(NVL(周山, 0)) 周山,SUM(NVL(车逻洞, 0)) + SUM(NVL(车逻闸, 0)) + SUM(NVL(南关, 0)) +SUM(NVL(头闸, 0)) + SUM(NVL(周山洞, 0)) + SUM(NVL(界首小闸, 0)) +SUM(NVL(子英闸, 0)) + SUM(NVL(周山, 0)) 合计FROM (SELECT TO_CHAR(MONITOR_DATE, 'yyyy') YEAR,TO_CHAR(MONITOR_DATE, 'yyyy') || TO_CHAR(MONITOR_DATE, 'mm') MON,TO_CHAR(MONITOR_DATE, 'mm') || '月' ||DECODE(TRUNC((TO_CHAR(MONITOR_DATE,'dd') - 1) / 10), 0, '1旬' ,1, '2旬', '3旬')DATETIME,SUM(车逻洞) / 10000 车逻洞,SUM(车逻闸) / 10000 车逻闸,SUM(车逻) / 10000 车逻,SUM(南关) / 10000 南关,SUM(头闸) / 10000 头闸,SUM(周山洞) / 10000 周山洞,SUM(界首小闸) / 10000 界首小闸,SUM(子英闸) / 10000 子英闸,SUM(周山) / 10000 周山FROM (SELECT B.SHORT_NAME, T.MONITOR_DATE, T.WATER_DAILYFROM WM_TD_WATER_DAILY TLEFT JOIN BI_TB_MONITOR_BI BON T.MONITOR_ID = B.IDWHERE T.REGION_ID = '6-100-018'AND T.MONITOR_DATE BETWEEN TO_DATE('2018-10', 'yyyy-MM') ANDTO_DATE('2018-12', 'yyyy-MM'))PIVOT(SUM(WATER_DAILY)FOR SHORT_NAME IN('车逻洞' 车逻洞,'车逻闸' 车逻闸,'车逻' 车逻,'南关' 南关,'头闸' 头闸,'周山洞' 周山洞,'界首小闸' 界首小闸,'子英闸' 子英闸,'周山' 周山))GROUP BY TO_CHAR(MONITOR_DATE, 'yyyy'),TO_CHAR(MONITOR_DATE, 'mm'),DECODE(TRUNC((TO_CHAR(MONITOR_DATE, 'dd') - 1) / 10),0,'1旬' ,1,'2旬','3旬')ORDER BY MON)GROUP BY ROLLUP(MON, DATETIME)

查询结果如下:

select后的不加case when的效果如下

mon用于第二层的排序 省略掉了

总结

这段SQL中用到了以下函数:

TO_DATE(),TO_CHAR(),BETWEEN,TRUNC(),DECODE(),NVL(),SUM(),PIVOT(  FOR  ),CASE  WHEN  THEN  ELSE  END,ROLLUP()

欢迎指正并优化SQL!

oracle 按旬统计并且每月小计 行转列 PIVOT函数 与分组小计 ROLLUP 函数相关推荐

  1. Oracle关于分组小计再合计

    其实在之前就写过mysql关于分组小计再合计,只是当时限于知识和眼界所限,所以给了一个不能算是通用的方案的方案,仅仅只是从效果上完成了任务.随着时间的发展,见识到的东西也多了些,近期在使用Oracle ...

  2. oracle如何总计,如何在Oracle中产生分组小计和总计?

    问题陈述: 您想在Oracle中找出总数,小计和总计. 解决方案: Oracle ROLLUP函数使用从右到左将中间级别汇总到任何总计的方法在多个级别上执行分组.为了演示ROLLUP功能,我们将创建一 ...

  3. 小福利,采用excel函数制作大屏可视化,用sumifs函数快速统计汇总数据,锁行锁列以及锁列不锁行

    小福利,采用excel函数制作大屏可视化,用sumifs函数快速统计汇总数据,锁行锁列以及锁列不锁行 源数据如下图所示 第一步处理源数据的效果是下图 其中根据年份变化,求总订单量.总销量.总销售额,只 ...

  4. Oracle之行转列pivot函数

    文章目录 方法一: Oracle行转列pivot函数 方法二:使用MAX DECODE 实现 方法一: Oracle行转列pivot函数 语法:pivot(任一聚合函数 for 需要转列的值所在列名 ...

  5. oracle unpivot 索引_Oracle 行转列pivot 、列转行unpivot 的Sql语句总结

    这个比较简单,用||或concat函数可以实现 select concat(id,username) str from app_user select id||username str from ap ...

  6. oracle非常量不能用于privot_Oracle 行转列(pivot、wm_concat、decode)使用总结(转载)...

    偶然需要了解,学习了这篇文章,转载记录一下 自:http://blog.csdn.net/jxzkin/article/details/7949629 1.创建测试数据CREATE TABLE CC ...

  7. Oracle 行转列pivot 、列转行unpivot 的Sql语句总结

    多行转字符串 这个比较简单,用||或concat函数可以实现 [sql] view plaincopy print? select concat(id,username) str from app_u ...

  8. sql server 分组小计和总计

    在 SQL Server 中,要对某一列进行分组并计算小计和总计,可以使用 GROUP BY 和 SUM() 函数. 例如,对于一个名为 "orders" 的表,其中有 " ...

  9. unpivot用法 oracle10g,Oracle 行转列pivot 、列转行unpivot 的Sql语句总结(转)

    多行转字符串 这个比较简单,用||或concat函数可以实现 1 select concat(id,username) str from app_user 2 3 select id||usernam ...

最新文章

  1. (C++)A+B 输入输出练习VI 每行的第一个数N,表示本行后面有N个数。
  2. Set Matrix Zeroes leetcode
  3. c++对那些类型的数据不能使用引用_基于js数据类型浅谈deepClone
  4. JAVA 解析JSON数据
  5. Android手机内存图片读取,有效解决Android加载大图片内存溢出的问题
  6. Quartz + spring 定时任务常见错误总结
  7. 计算机组成原理,P函数,深入浅出计算机组成原理学习笔记:第五讲
  8. qq安全保护进程更改计算机,分享win10电脑系统关闭qq安全防护进程的步骤
  9. 违反Apache 2.0许可证再分发被指控,火山引擎回应
  10. magrittr | R语言的管道操作符
  11. 随想录(png的读取和显示)
  12. 【Python网络爬虫】规则#20181023
  13. jsp中target=_blank的用法
  14. 跨境电商竞品分析报告
  15. Max函数、Min函数
  16. Java 获取服务器ip地址
  17. 关于schema文档
  18. pymysql获取要查询的字段名(列名)
  19. MyBatis一对多,多对一,多对多
  20. 吊打面试官,笑对 2022 金三银四,2022年最全面试真题大汇总

热门文章

  1. unity3d Daikon GUI 图片查看器 Demo 说明
  2. 华为android10手机指纹,华为P10这些指纹功能你知道几个?
  3. 屏幕扩展之将手机变成显示器-Wired Xdisplay
  4. 100集华为HCIE安全培训视频教材整理 | Agile Controller终端安全管理特性(五)
  5. [xhr4412][extension 4] u-boot-2020.07 DM9621 网卡驱动移植
  6. 日本银发经济科技范儿十足
  7. gclient 设置代理问题
  8. 获取jar包中的文件,及遍历jar包中的文件
  9. self和Self、== 和===的区别
  10. CSS中position属性(relative,absolute,fixed)和display中的inline-block