深入理解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关联查询的理解

 

谢谢!

 

posted @ 2019-05-10 14:45  布里塔  阅读(1723)  评论(0编辑  收藏  举报