本系列仅为小明在写SQL过程中,由浅入深遇到的一些问题、以及最后解决方案。我知道这其中有些问题,高手在12岁的时候就已经知道答案了,小明可能比你们慢了一点。
本文解决的问题:
1、有条件计数
2、去重后左连接
3、自关联,每对只取一条
文本演示code,默认用 SAS SQL 来演示,因为大家可能对 SAS 还是比较熟悉一些,但有些语句 SAS SQL 不支持的,改用其他。
1、有条件计数
以 SAS 中 sashelp 自带的 Cars 数据为例。
【问题:想计算每个 Make 下面,engine size >=3 的占比情况】
我们知道,计算每个 Make 的个数用:
select Make, count(*) from cars;
但如果要计算满足条件的个数,就要用
sum( case when ... then 1 else 0 end) as new_name
比如这里计算每个 Make 中 engine size >=3 的个数和占比:
结果为:
2、去重后左连接
对两个表进行关联时,通常有左连接(left join)、右连接(right join)、全连接(full join)、内连接(inner join)。
【问题:table1 左连接 table2 时,想对 table2 的数据按照 id 去重再做连接】
如上图所示,id=a 有多条数据,连接时只想连一条,此时对 table2 做 distinct 是无法满足的:
- distinct id,则 value2,value3的信息就丢了;
- distinct id value2 value3 也不行,也为 value2 和 value3 是不重复的。
此时可以用
row_number() over(partition by id order by value2) as r
的方式来去重。由于 SAS 的 sql 不支持这个语句,因此我们用阿里ODPS来演示。
select *, row_number() over(partition by id order by value2) as r from table2
partition by id 表示按照 id 分组,order by value2 表示分组后按照 value2 来排序,按照顺序依次给一个序号 r=1,2...,如果想去重,只要指定 r=1 即可。
(PS:这里 r 分配给组内每条数据的值一定是唯一的,即使 value2 有重复,r 也是唯一的,因此用于去重正好)
我们尝试去重后左关联:
结果:
3. 自关联,每对只取一条
如下图,
【问题:想对 table1 做自关联,但相同一对只出现一次,比如 a-b 有了,那么b-a 就不需要了】
只要在关联的时加上条件 where a.id<b.id 即可。
结果: