with用法(oracle和mysql均支持,mysql版本8以上)

场景:

        先说下我遇到的使用场景:查询一组统计数据,在此基础上做个日均,求均值,由于字段多,直接在原先基础上改动比较大,想的是直接使用union连接一条均值不就行了,看下图

SELECT
	to_char( to_date( tjrq, 'yyyymmdd' ), 'yyyy"年"mm"月"dd"日"' ) tjrq,
	nvl( yjjj, 0 ) yjjj,
	nvl( qyxf, 0 ) qyxf,
	nvl( dgmhs, 0 ) dgmhs 
FROM
	(
        SELECT sjly,tjrq,sum( ztrs ) ztrs 
        FROM
	        ( SELECT zrq, sjly, tjrq, min( ztrs ) ztrs FROM SKMTC_RYSJ_TJ GROUP BY zrq,             
              sjly, tjrq ) 
        GROUP BY sjly,tjrq 
	) 
pivot (sum( ztrs ) FOR sjly IN ( '应检尽检' AS yjjj, '区域协防' AS qyxf, '大规模核酸检测'         
     AS dgmhs )) 
WHERE
	tjrq BETWEEN '20220814' 
	AND '20220831'

union

select '日均',round(avg(yjjj)), round(avg(qyxf)), round(avg(dgmhs)) from 
(
	SELECT
	    row_number () over ( ORDER BY tjrq DESC ) AS xh,
	    to_char( to_date( tjrq, 'yyyymmdd' ), 'yyyy"年"mm"月"dd"日"' ) tjrq,
	    nvl( yjjj, 0 ) yjjj,
	    nvl( qyxf, 0 ) qyxf,
	    nvl( dgmhs, 0 ) dgmhs 
    FROM
	(
        SELECT sjly,tjrq,sum( ztrs ) ztrs 
        FROM
	    ( SELECT zrq, sjly, tjrq, min( ztrs ) ztrs FROM SKMTC_RYSJ_TJ GROUP BY zrq, sjly,         
          tjrq ) 
        GROUP BY sjly,tjrq 
	) 
    pivot (sum( ztrs ) FOR sjly IN ( '应检尽检' AS yjjj, '区域协防' AS qyxf, '大规模核酸检 
           测' AS dgmhs )) 
WHERE
	tjrq BETWEEN '20220814' 
	AND '20220831'
) 

 

 

但此时sql重复了,union前的sql在求均值被重复使用,sql冗余,可读性差,对此sql进行改造就用到了with

语法:

♡单个别名

WITH <别名-后续使用的表名> AS (查询的sql)  SELECT <查询字段> FROM <别名>;

♡多个别名

WITH <别名1>  AS (sql1),<别名2>  AS (sql2)
SELECT <查询字段>  FROM <别名1>, <别名2>  WHERE <条件>;

上面例子中union前的改造:temp是创建的公共临时表 as()内是查询的sql,就是数据来源

                后面操作查询就直接从临时表里查询即可

with temp as  (
	SELECT
		to_char( to_date( tjrq, 'yyyymmdd' ), 'yyyy"年"mm"月"dd"日"' ) tjrq,
		nvl( yjjj, 0 ) yjjj,
		nvl( qyxf, 0 ) qyxf,
		nvl( dgmhs, 0 ) dgmhs 
	FROM
	    (SELECT sjly,tjrq,sum( ztrs ) ztrs 
         FROM
			( SELECT zrq, sjly, tjrq, min( ztrs ) ztrs FROM SKMTC_RYSJ_TJ GROUP BY zrq,         
              sjly, tjrq ) 
		 GROUP BY sjly,tjrq 
		) 
        pivot 
        (sum( ztrs ) FOR sjly IN ( '应检尽检' AS yjjj, '区域协防' AS qyxf, '大规模核酸检测' 
         AS dgmhs )) 
	WHERE tjrq BETWEEN '20220814' AND '20220831'
) select * from  temp 

针对如上结果只需在temp后union即可

with temp as  (
	SELECT
		to_char( to_date( tjrq, 'yyyymmdd' ), 'yyyy"年"mm"月"dd"日"' ) tjrq,
		nvl( yjjj, 0 ) yjjj,
		nvl( qyxf, 0 ) qyxf,
		nvl( dgmhs, 0 ) dgmhs 
	FROM
	    (SELECT sjly,tjrq,sum( ztrs ) ztrs 
         FROM
			( SELECT zrq, sjly, tjrq, min( ztrs ) ztrs FROM SKMTC_RYSJ_TJ GROUP BY zrq,         
              sjly, tjrq ) 
		 GROUP BY sjly,tjrq 
		) 
        pivot 
        (sum( ztrs ) FOR sjly IN ( '应检尽检' AS yjjj, '区域协防' AS qyxf, '大规模核酸检测' 
         AS dgmhs )) 
	WHERE tjrq BETWEEN '20220814' AND '20220831'
) select * from  temp 
   union select '日均',round(avg(yjjj)), round(avg(qyxf)), round(avg(dgmhs)) from temp

查询结果跟上面一致

 with的优点:
    

一个是重复的查询内容可以只调用一次,一是增加了代码的阅读性

 如果遇到多个同一子查询时,采用此方式效率比一般子查询高,而且代码结构更清晰易懂。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值