深入理解SQL关联查询->不等值连接
需求 : 针对每只债券symbol每天tdate的不同剩余期限term对应的收益率yield , 打上标签flag ('到期','行权')
flag字段判断规则 对于一个代码 , 如果只有一条数据 则无论DataSource的值 , flag='到期'
如果有两条一条数据 则term小的为行权 , term大的为到期
前提 : 对于一只债券 第2列DataSource的范围是('01','05') 可能是其中任意一个 也可能是两条都有
1 drop table if exists #a 2 create table #a (symbol varchar(10),datasource varchar(5),yield float,term int ,tdate varchar(10)) 3 insert into #a 4 (symbol,datasource,yield,term,tdate) -- 该行可以省略 因为values是全部依次对应的 5 values 6 ('001','01',round(rand()*10,2),floor(rand()*1000),'20190501'), 7 ('001','05',round(rand()*10,2),floor(rand()*1000),'20190501'), 8 ('002','01',round(rand()*10,2),floor(rand()*1000),'20190501'), 9 ('003','01',round(rand()*10,2),floor(rand()*1000),'20190501'), 10 ('003','05',round(rand()*10,2),floor(rand()*1000),'20190501'), 11 ('004','05',round(rand()*10,2),floor(rand()*1000),'20190501'), 12 ('001','01',round(rand()*10,2),floor(rand()*1000),'20190502'), 13 ('001','05',round(rand()*10,2),floor(rand()*1000),'20190502'), 14 ('002','01',round(rand()*10,2),floor(rand()*1000),'20190502'), 15 ('003','01',round(rand()*10,2),floor(rand()*1000),'20190502'), 16 ('003','05',round(rand()*10,2),floor(rand()*1000),'20190502'), 17 ('004','05',round(rand()*10,2),floor(rand()*1000),'20190502') 18 19 select * from #a 20 21 select a.*,flag=case when b.symbol is not null and a.term<b.term then '行权' else '到期' end 22 from 23 ( 24 select * from #a 25 )a 26 left join 27 ( 28 select * from #a 29 )b 30 on a.symbol=b.symbol and a.tdate=b.tdate and a.datasource<>b.datasource -- 注意关联条件 31 32 drop table #a
关键在于连接条件on 中的不等号
注意flag后面case when 中包含的意义有很多
分为以下几种情况:
1.能关联到b表 则如果a.term<b.term 则 行权 否则 到期
2.关联不到b表 则必定为到期
注意 这里a表的所有数据都会原原本本的返回 , b表的字段只是用来写flag字段的辅助字段 ,只是这里的b表和a表是同一张表
最终返回的是a和b的所有的字段 , 我们在select后面加上a.*筛选出需要的字段
ps:实际中同一只代码两个term不会是相等的 这里用了随机数有很小的概率出现相等 , 可以忽略
这个不等值连接可以大大提升对SQL关联查询的理解
谢谢!