SQL Cookbook 系列 - 使用数字

  1. 计算平均值
  2. 求某列中的最小值最大值
  3. 对某列的值求和
  4. 求一个表的行数
  5. 求某列值的个数
  6. 生成累积和
  7. 生成累乘积
  8. 计算累积差
  9. 计算模式
  10. 计算中间值
  11. 求总和的百分比
  12. 对可控列做聚集
  13. 计算不包含最大值和最小值的均值
  14. 把字母数字串转换为数值
  15. 更改累积和中的值

1.计算平均值
select deptno,avg(sal) as avg_sal from emp group by deptno;

2.求某列中的最小值最大值
select deptno,min(sal) as min_sal,max(sal) as max_sal from emp group by deptno;

3.对某列的值求和
select sum(sal) from emp group by deptno;

4.求一个表的行数
select count(*) fom emp group by deptno;

5.求某列值的个数,非null值的个数
select count(comm) from emp group by deptno;

6.生成累计和
db2,oracle : select ename,sal,sum(sal) over (order by sal,empno) as running_total from emp order by sal;
mysql,postgreSQL,sqlserver : select e.ename,e.sal,(select sum(d.sal) from emp d where d.empno<=e.deptno) as running_total from emp e order by running_total;

7.生成累乘积
db2,oracle : select empno,ename,sal,exp(sum(ln(sal)) over (order by sal,empno)) as running_prod from emp where deptno=10;
mysql,postgresql,sqlserver : select e.empno,e.ename,e.sal,
(select exp(sum(ln(d.sal))) from emp d where d.empno<=e.empno and e.deptno=d.deptno) as running_prod
from emp e where e.deptno=10
Note:sqlserver 要使用log代替ln

8.计算累计差
db2,oracle : select ename,sal,sum(case when rn=1 then sal else -sal end) over (order by sal,empno) as running_diff from
(select empno,ename,sal,row_number() over (order by sal,empno) as rn from emp where deptno=10 ) x;
mysql,postgresql,sqlserver : select a.empno,a.ename,a.sal,
(select case when a.empno=min(b.empno) then sum(b.sal) else sum(-b.sal) end from emp b where b.empno<=a.empno and b.deptno=a.deptno ) as rnk
from emp a where a.deptno=10;
9.计算模式
模式:对给定数据集出现最频繁的元素
db2,sqlserver,oracle : select sal from ( select sal,dense_rank() over (order by cnt desc) as rnk
from (select sal,count(*) as cnt from emp where deptno=20
group by sal) x ) y where rnk=1;
mysql,postgreSQL: select sal from emp where deptno=20 group by sal
having count(*)>=
all(select count(*) from emp where deptno=20 group by sal);

10.计算中间值
db2 : select avg(sal) from (select sal,count(*) over() total,cast(count(*) over() as decimal)/2 mid,
ceil(cast(count(*) over as decimal)/2) next,
row_number() over (order by sal) rn from emp where dept=20)
x where (mod(total,2)=0 and rn in(mid,mid+1)) or
(mod(total,2)=1 and rn=next);
mysql,postgresql : select avg(sal) from (select e.sal from emp e,emp d
where e.deptno=d.deptno and e.deptno=20 group by e.sal
having sum(case when e.sal=d.sal then 1 else 0 end)
>=abs(sum(sign(e.sal-d.sal))));
oracle 10g : select median(sal) from emp where deptno=20;
sqlserver: select avg(sal) from (select sal,count(*) over() total,cast(count(*) over() as decimal)/2 mid,
ceil(cast(count(*) over as decimal)/2) next,
row_number() over (order by sal) rn from emp where dept=20)
x where (total%2=0 and rn in(mid,mid+1)) or
(total%2=1 and rn=next);

11.求总和的百分比
mysql,postgreSQL: select (sum(case when deptno=10 then sal end)/sum(sal))* 100 as pct
from emp;
db2,oracle,sqlserver: select distinct (d10/total)*100 as pct from
(select deptno,sum(sal) over() total,sum(sal) over (partition by deptno) d10 from emp ) x where deptno=10;

12.对可空列做聚集
select avg(coalesce(comm,0)) as avg_comm from emp where deptno=30;

13.计算不包含最大值和最小值的均值
mysql,postgresql : select avg(sal) from emp where sal not in
(select min(sal) from emp,select max(sal) from emp);
db2,oracle,sqlserver : select avg(sal) from (
select sal,min(sal) over() min_sal,max(sal) over max_sal from emp
) x where sal not in (min_sal,max_sal);

14.将字母数字转换为数值
db2 : select cast(replace(translate(ename,repeat('#',26),'qwertyuioplkjhgfdsazxcvbnm'),'#','') as integer) as num from emp;
oracle,postgresql : select cast(replace(translate(ename,'qwertyuioplkjhgfdsazxcvbnm',rpad('#',26,'#')),'#','') as integer) as num from emp;
mysql和sqlserver暂时不支持translate函数

15.更改累积和中的值
虽然表中数据均是正值,但是在某种类型下是以负值累计的
db2,oracle : select case when trx='PY' then 'payment' else 'purchase' end trx_type,amt,
sum(case when trx='PY' then -amt else amt end) over (order by id,amt) as bal
from py_table;
mysql,postgresql,sqlserver : select case when v1.trx='PY' then 'payment' else 'purchase' end as trx_type,v1.amt,(select sum(case when v2.trx='PY' then -v2.amt else v2.amt end) from v v2 where v2.id<=v1.id) as bal from v v1;


Note:使用数字统计的时候,要进行合理的检查,特别是在多条件以及表联接查询的时候

猜你喜欢

转载自blog.csdn.net/seacean2000/article/details/80984994