分享6个SQL小技巧

2023年 7月 19日 64.5k 0

原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,非公众号转载保留此声明。

简介

经常有小哥发出疑问,SQL还能这么写?我经常笑着回应,SQL确实可以这么写。其实SQL学起来简单,用起来也简单,但它还是能写出很多变化,这些变化读懂它不难,但要自己Get到这些变化,可能需要想一会或在网上找一会。

各种join

关于join的介绍,比较流行的就是这张图了,如下:
join
简单的解释如下:

  • join:内联接,也可写成inner join,取两表关联字段相交的那部分数据。
  • left join:左外联接,也可写成left outer join,取左表数据,若关联不到右表,右表为空。
  • right join:右外联接,也可写成right outer join,取右表数据,若关联不到左表,左表为空。
  • full join:全联接,也可写成full outer join,取左表和右表中所有数据。

但注意上图,里面还有几个Key is null的情况,它可以将两表相交的那部分数据排除掉!
也正是因为这个特性,一种很常见的SQL技巧是,用left join可替换not existsnot in等相关子查询,如下:

select * from tableA A 
where not exists (select 1 from tableB B where B.Key=A.Key)

-- 使用left join的等价写法
select * from tableA A 
left join tableB B on B.Key=A.Key where B.Key is null

也比较好理解,只有当左表的数据在右表中不存在时,B.Key is null才成立。

查询各类别最大的那条数据

比如在学籍管理系统中,有一类很常见的需求,查询每学科分数最高的那条数据,有如下几种写法:

select * from stu_score s 
where s.course_id in ('Maths','English') 
and s.score = (select max(score) from stu_score s1 where s1.course_id = s.course_id)

比较好理解,考分最高其实就是过滤出分数等于最大分数的记录。

在不能使用子查询的场景下,也可转换成join,如下:

select * from stu_score s 
left join stu_score s1 on s1.course_id = s.course_id and s1.score > s.score
where s.course_id in ('Maths','English') and s1.id is null

这和前面用left join改写not exists类似,通过s1.id is null过滤出left join关联条件不满足时的数据,什么情况left join关联条件不满足呢,当s表记录是分数最大的那条记录时,s1.score > s.score条件自然就不成立了,所以它过滤出来的数据,就是学科中分数最大的那条记录。

一直以来,我看到SQL的join的条件大都是a.field=b.field这种形式,导致我以为join只能写等值条件,实际上,join条件和where中一样,支持> s.score) DATE_SUB(now(), INTERVAL 1 DAY)
union all
select count(*) from order where add_time > DATE_SUB(now(), INTERVAL 1 WEEK)
union all
select count(*) from order where add_time > DATE_SUB(now(), INTERVAL 1 MONTH)

其实扫描一次表也可以实现,用sum来代替count即可,如下:

select sum(IF(add_time > DATE_SUB(now(), INTERVAL 1 DAY)), 1, 0) day_order_cnt,
sum(IF(add_time > DATE_SUB(now(), INTERVAL 1 WEEK)), 1, 0) week_order_cnt,
sum(IF(add_time > DATE_SUB(now(), INTERVAL 1 MONTH)), 1, 0) month_order_cnt
from order where add_time > DATE_SUB(now(), INTERVAL 1 MONTH)

IF是mysql的逻辑判断函数,当其第一个参数为true时,返回第二个参数值,即1,否则返回第三个参数值0,然后再使用sum加起来,就是各条件为true的数量了。

数据对比

有时,我们需要对比两个表的数据是否一致,最简单的方法,就是在两边查询出结果集,然后逐行逐字段对比。

但是这样对比的效率比较低下,因为它要两个表的数据全都查出来,其实我们不一定非要都查出来,只要计算出一个hash值,然后对比hash值即可,如下:

select BIT_XOR(CRC32(CONCAT(ifnull(column1,''),ifnull(column2,'')))) as checksum
from table_name where add_time > '2020-02-20' and add_time

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论