理解sql

数据变换

实际上,sql描述的是一系列的数据变换,我们跳出sql,来理解一下数据变换。

我们平时写代码,通常的视角在于解决某一个问题的过程。
比如说,web应用,我们对流量的理解会是,我们代码描述了一个过程,每个流量在我们的代码中流动,最终转换成返回结果,流回调用方。
我们换种思路。流量是个数据包,web应用就是个流水线的一个变化工具。对于每一个流量,我们的web应用会将这个流量包转换成返回结果,返回给调用方。

数据变换,就是通过一些操作,把一个数据集转成另一个数据集。

基本数据变换

单数据集变换

  • 映射,也就是一对一变换,通过变换函数,将数据集的每个元素变成另一个元素,在fp中表现为map
  • 过滤,通过判断函数,将数据集划分成两个分块,其中一块形成另一个数据集,在fp中表现为filter
  • 排序,通过比较函数,将数据集进行排序
  • 分组,通过分组函数,将数据集根据分组函数值进行分组,把相同分组函数值的放进同一个元素。通常分组后表现为,分组函数值->[子数据集],在fp中表现为group或者collect
  • 拆分,分组的逆运算,如果数据集中每个元素都是数组,那么拆分操作,就是把数组里面的元素,平铺开,形成一个新的数据集,在fp中表现为flatmap
    [[1,2,3],[4,5,6]]->[1,2,3,4,5,6]

多数据集变换

  • 合并,这个不用解释
  • 关联,通过关联id,将两个数据集合并,其实就是分别对两个数据集进行分组,相同组,合并成一行

sql

sql的语法其实就实现结构化数据的数据变换。

  • 映射:select
  • 过滤:where
  • 排序:order
  • 分组:group by,但sql会为分组后的子数据集根据聚合函数合并成一个元素
  • 拆分:(mysql未实现)
  • 合并:union all
  • 关联:join,sql会将相同组的两个子数据集进行笛卡尔积;除此之外,对空子数据集的处理方式又分为left join, inner join, right join, full join

如何写sql

步骤:

  • 先把原始数据集和目标识别出来
  • 寻找一系列基本数据变换,使得原始数据集可以通过这一系列基本数据变换,转换成目标数据集
  • 优化,将部分可以写在一起的语法放一起。如果懒得优化,也可以用子查询嵌套

例子:

取出公司9月的销售总额

  • 原始数据集:销售明细
  • 过滤:根据时间为9月,形成新的数据集,形成的数据集是,公司9月的销售明细
  • 映射:销售明细->销售额,形成的数据集是,公司9月的销售额列表
  • 分组:最后要求销售总额,所以肯定分成1组,聚合函数为,累加

根据上述步骤,可以形成初步sql:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
select
1, sum(amount)
from
(--映射
select
amount
from
(--过滤
select *
from A
where month = 9
) t1
) t2
group by 1;

当然这个sql也是对的,简化sql:

1
2
3
select sum(amount)
from A
where month = 9

大家平时在写代码时,可以有意的往数据变换想,或者直接用fp编程思想来写代码。

sql常见的坑

  • mysql只是个方言,大家尽可能用标准的sql来写,以免出现难以理解的bug

  • order,排序的是结果集,而其他语法,操作的是原始集,因此在写操作字段时应当注意,避免莫名其妙的找不到字段,比如说:

    1
    2
    3
    4
    select A as B
    from table
    where A = "123"
    order by B

    上述例子,where用的是A字段,是table的字段,而order用的是B,是结果集里面的字段,结果集中,A是不存在的,只有一个字段B。
    还是上面那个问题,mysql是个方言,有可能mysql的order by中可以写A,也会排序,但不建议大家那么写。否则,到其他数据库,会难以理解出现的问题

  • 。。。

excel

写多了sql,再去理解excel的操作,数据变换的都在excel中体现了。
过滤->筛选 分组->透视表 关联->lookup 。。。