SQL进阶--用关联子查询比较行与行

1、增长、减少、维持现状

-- 建表
drop table if exists sales;
create table sales(
year1 year,
sale int8
);
insert into sales values(1990, 50);
insert into sales values(1991, 51);
insert into sales values(1992, 52);
insert into sales values(1993, 52);
insert into sales values(1994, 50);
insert into sales values(1995, 50);
insert into sales values(1996, 49);
insert into sales values(1997, 55);

展示与上一年的比较

select a.year1, a.sale,
       case when a.sale = b.sale then '→'  -- 持平
            when a.sale > b.sale then '↑'  -- 增长
            when a.sale < b.sale then '↓'  -- 减少
       else '-' end as var
  from sales a left join sales b
    on b.year1 = a.year1 - 1  -- 为了将没有可比较年份也展示出来
 order by year1
;

这里写图片描述

查询每一年与过去最近的年份之间的营业额之差

select b.year1 as pre_year,
       a.year1 as now_year,
       a.sale  as pre_sale,
       b.sale  as now_sale,
       a.sale - b.sale as diff
  from sales a left join sales b  
    on b.year1 = (select max(year1) from sales c where a.year1 > c.year1)  -- 非等值连接
 order by now_year;

2、移动累计值

-- 建表
drop table if exists accounts;
create table accounts(
prc_date date,
prc_amt int8
);
insert into accounts values(20061026,12000);
insert into accounts values(20061028,2500);
insert into accounts values(20061031,-15000);
insert into accounts values(20061103,34000);
insert into accounts values(20061104,-5000);
insert into accounts values(20061106,7200);
insert into accounts values(20061111,11000);

求累计值:使用冯。诺依曼型递归集合


select prc_date, a1.prc_amt,
       (select sum(prc_amt)    -- 在求秩的时候用是count()
          from accounts a2
         where a1.prc_date >= a2.prc_date) as onhand_amt
  from accounts a1
 order by prc_date;

这里写图片描述

3、查询重叠的时间区间

思路:
(1)自己入住日期在他人住宿期间内
(2)自己离店日期在他人住宿期间内
(3)自己的入住日期和离店时间都在他人住宿期间内

-- 建表
drop table if exists accounts;
create table accounts(
prc_date date,
prc_amt int8
);
insert into accounts values(20061026,12000);
insert into accounts values(20061028,2500);
insert into accounts values(20061031,-15000);
insert into accounts values(20061103,34000);
insert into accounts values(20061104,-5000);
insert into accounts values(20061106,7200);
insert into accounts values(20061111,11000);

查询重叠住宿

select reserver, start_date, end_date
  from reservations r1
 where exists
       (select * from reservations r2
          where r1.reserver <> r2.reserver
            and (  (     r1.start_date between r2.start_date
                                           and r2.end_date   -- (1or  r1.end_date   between r2.start_date
                                           and r2.end_date)  -- (2or(     r2.start_date between r1.start_date
                                           and r1.end_date
                     and r2.end_date   between r1.start_date
                                           and r1.end_date)  -- (3))  
        );

练习

求累计平均

select prc_date, a1.prc_amt,
       (select round(avg(prc_amt),2)
          from accounts a2
         where a1.prc_date >= a2.prc_date) as onhand_min  -- 求累计平均
  from accounts a1
 order by prc_date
 ;

这里写图片描述

内容多来自 《SQL进阶教材》,仅做笔记。练习部分代码均为原创。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Scc_hy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值