欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

sql 子查询_精益SQL —— “子查询”的前世今生

程序员文章站 2022-06-01 20:15:42
...

照例,本章从一道面试题开始。

如果你需要处理的数据量非常大,你有没有什么好办法可以改善效率?

数据分析师前辈们在这里肯定一下能理解所谓的数据量非常大是个什么概念,但对于新手如我来说,第一次碰到这个问题,首先冒出来的疑惑就是:

  • 数据量非常大?能有多大?我平时训练接触到的数据就几百几千条啊。。。
  • 数据量大是吧,那不是有大数据平台吗,什么hadoop,hive全都上,然后加服务器啊,加加加!!!但是,问题是我没用过,我也不知道啊= =

然后老实如我,就这么老实一回答,再然后,就没有然后了。(面试官,你别走~)

当真正进入到现实工作环境才知道,你接触到的数据量可能是billion级别的,你的每一次SQL执行,都影响着全公司同事的效率。为了看某个指标或做一次统计,一次性跑四五段完整的select语句,一次跑一两个小时,是非常普遍的事情。

处理这么大的数据量,有什么好办法可以改善效率呢?我的答案是:第一,尽可能减少select的嵌套;第二,分步骤。

减少嵌套,就类似于减少for循环的嵌套一样,很好理解。

分步骤,有两个好处,一是让你的取数逻辑非常清晰,便于以后自己和同事的阅读,二是减少冗余代码和重复执行。那么,如何分步骤呢,就要用到“视图”这个概念。

看到这里,你可能会说,不对啊博主,你明明要说的是“子查询”,怎么扯到“视图”了。

实际上,“视图”正是“子查询”的前世。首先来看“视图”的定义:

视图,就是指保存好的select语句。

什么叫作保存好的?就是我建一张临时表,这个临时表的数据来源哪里呢,来源于我想要的select语句。所以写法就是:

create view 视图名 ( <列名1>, <列名2>, ... ) as
<select 语句>

但是这个视图并不是你建了一张存入数据库的表,你执行这段代码以后,程序只是知道了你想要建一张长这样的表,表名叫什么,但是它不会给你把数据跑出来存进去,只有当你之后通过from调用这张表的时候,程序才会给你执行下面的select语句。

view,是MySQL和Spark的写法,在Hive中用的是temporary table,在Teradata中用的是volatile table。temporary的意思是临时性的,volatile的意思是挥发性的、不稳定的,所以通过比较各个DBMS对视图的命名,可以帮助我们加深对视图的理解。

那么,什么是子查询呢?子查询就是一次性视图,是视图结构中的select语句部分,也就是我们常理解的select语句嵌套。具体来说,子查询有三种类型:

  1. 普通子查询,形如:
select ...
from (select ... from ...);

2. 标量子查询,是指只返回一个值的普通子查询。可以嵌套在select、from、where等等中。

3. 关联子查询,是指select嵌套在where子句的条件中,主要用在分组后在组内进行比较等。比如说:

SELECT product_type, product_name, sale_price
FROM Product AS P1
WHERE sale_price > (SELECT AVG(sale_price) FROM Product AS P2 WHERE P1.product_type = P2.product_type GROUP BY P2.product_type)
;

表示“选出各个商品种类中高于该商品种类的平均销售单价的商品”。

所以我们知道了,在细分组内进行比较时,需要使用关联子查询。

以上就是目前我对子查询的理解。对于开头的问题,如果大家有不同见解,欢迎讨论,相互学习!如果有前辈看到我的浅见,也欢迎指教!