在工做中经常使用到的SQL

前言

只有光头才能变强。html

文本已收录至个人GitHub仓库,欢迎Star:github.com/ZhongFuChen…java

最近在公司作了几张报表,还记得刚开始要作报表的时候都快把SQL给忘光了(当时在广州休假了1个月多,在实习期间也没咋写过SQL),回到公司的第一个需求就是作报表。git

因而我很不要脸地跟带个人学长说:“SQL我好像忘光了,group 分组查询好像都忘得差很少了,我得复习一下”。github

这篇文章来记录一下我曾经忘掉的group查询、join查询等一些比较实用/经常使用的SQL正则表达式

  • 本文主打通俗易懂,不涵盖任何优化(适合新手观看)

1、回顾group 查询

group查询就是分组查询,为何要分组查询?由于咱们想按某个维度进行统计。下面来看个图:sql

如今个人数据以下

好比说,我想知道:天天Java3y这个公众号的点击量是多少。按咱们人工而言,思路很简单:把相同的天数以及公众号名称为Java3y的数据找出来,再将每一个点击量相加,就得出告终果了。json

步骤

用上SQL咱们可能会这样写:数组

select name,time,sum(pv) as pv  
from xxx_table 
where name = 'Java3y' group by name,time
复制代码

1.1 group 查询可能存在的误解

记得有一天,有个群友在群上问了一个问题:markdown

群里边的一个问题

其实他的需求很简单:检索出数据分组后时间最高的记录。但他是这样干的:函数

  1. 把先按照时间 order by
  2. order by后的记录进行分组

示例图:

群里面的一个图

1.2 形成这个误解的可能缘由

有的工具能够支持这种的写法:

select * from xxx_table group by name
复制代码

这种写法没有被禁止,并能够得出结果,好比获得的结果是:

Java4y    20  7月15号
Java3y    30  7月15号
复制代码

这种写法实际上是不合理的,要知道的是:使用group by分组统计以后,咱们的select 后面只能跟着group by 的字段,或者是聚合函数。

group by规则

由于,咱们对数据进行了分组查询,数据的分布状况,咱们是不关心的

记住:先分组,后统计(先把数据归类后,再对相同的数据进行统计)

1.3 group查询最经常使用的SQL

去重是咱们常常会遇到的问题,打个比方说,因为各类缘由(不论是业务上仍是说是脏数据),如今我有两条重复的数据(除了ID,其他的字段都是相同的):

重复的数据

我这边只但愿留下某一条记录做为查询结果就行了,咱们能够写下如下的SQL:

select * from user where id in(
   select min(id) from user where name = 'Java3y' and pv = 20 and time='7-25' group by name,pv,time;
)
复制代码

上面这条SQL是很是很是实用的,除了我说的去重之外,其实咱们能够再”思考“一下:

  • 上面已经说了,使用group by分组统计以后,咱们的select 后面只能跟着group by 的字段,或者是聚合函数。
  • 不少时候咱们group by了之后,还想要查询结果中包含group by以外的字段(通常状况下,咱们都不可能将group by 涵盖全部的字段),咱们就能够上面那样,将查询后的结果做为子查询,放在外部查询的where 子句后,这样外部查询是能够select 出其余字段的。

(SQL写得比较少的朋友可能没什么感触啊,但我但愿上面那种写法你们可以记住,之后必定会遇到相似的状况的)

2、回顾join查询

join查询不知道你们在刚学的时候是怎么理解的,反正我当初好像就挺迷迷糊糊的。我以为join查询能够简单理解成这样:我想要的查询结果,一张表搞不掂,那我就join另外一张表

好比说,如今我有两张的表:

第一张表

第二张表

如今我想知道在7月25号时:每一个公众号的点击量、公众号名称、号主名称、公众号的建立日期

  • 显然,咱们会发现一张表搞不掂啊,某些数据要依赖于另外一张表才能把数据"完整"展现出来

那join其实就是把两张表合起来的一个操做:

join其实就是一个合并的操做

两张表合并起来之后咱们就会发现,这张“大表”就含有这两张表的全部字段啦,那我想要什么都有了!

值得注意的是:在join的时候,会产生笛卡尔积(至于什么是笛卡尔积我这里就不说了,反正咱们要记住的是join表时必定要写关联条件去除笛卡尔积

另外,left joinright join也是咱们常常用到,若是咱们单纯写join关键字,那会被当成是inner join 。下面我简单解释一下:

  • 上面说了,在join的时候必定要写关联条件,若是是inner join的话,只有符合关联条件的数据才会存在最大表中
  • 若是是left join的话,即使关联条件不符合,左边表的数据必定会存在大表中
  • 若是是right join的话,即使关联条件不符合,右边表的数据必定会存在大表中

看下面的图:

join

此时咱们的两张表关联的条件是“公众号” :若是是inner join,那么最后咱们的表只有两条记录。若是是left join ,那么最后咱们的表有三条数据。若是是right join,那么咱们最后的表只有两条数据

3、回顾case when

SQL中的case when then else end用法其实跟咱们程序语言中的if-else非常相似,在写SQL的时候也经常会用到。

我用得比较多的语法以下:

CASE WHEN sex = '1' THEN '男'
         WHEN sex = '2' THEN '女'
ELSE '其余' END   
复制代码

在when后面能够跟多个表达式,好比说:

CASE WHEN sex = '1' and name ='Java3y' THEN '男'
         WHEN sex = '2' and name ='Java4y' THEN '女'
ELSE '其余' END   
复制代码

若是要为case when表达式取别名,在end 关键字后边直接加就行了

更多用法详情参考:

4、一些经常使用的函数

4.1 hive和presto解析json

我这边会有这种状况:将json数据存到MySQL上。我去网上搜了一下以及问了同事,为何要将json存到MySQL的字段上时,他们的答复都差很少:

  • 在MySQL存json数据,这样方便扩展啊。若是那些字段不须要用到索引,改动比较频繁,你又不想改动表的结构,那能够存join。
  • ps:在MySQL 5.7版本之后支持json类型

参考资料:

我这边作报表通常来hive或presto上搞的,因此解析json的也是在那上面。

hive解析json函数:

get_json_object(param1,'$.param2')

-- 若是是数组
get_json_object(xjson,'$.[0].param2')
复制代码

presto 对json的处理函数:

-- 数组 (去除第index个json)
 json_array_get(xjson,index) 
 
 -- 单个jsoin对象
 json_extract(xjson,'$.param2')
复制代码

参考资料:

4.2 时间函数

昨天/近7天/本月按照这种指标来查询也是很是常见的:

昨天

SELECT * FROM 表名 WHERE TO_DAYS( NOW( ) ) - TO_DAYS( 时间字段名) <= 1

7SELECT * FROM 表名 where DATE_SUB(CURDATE(), INTERVAL 7 DAY) <= date(时间字段名)

近30SELECT * FROM 表名 where DATE_SUB(CURDATE(), INTERVAL 30 DAY) <= date(时间字段名)

本月

SELECT * FROM 表名 WHERE DATE_FORMAT( 时间字段名, '%Y%m' ) = DATE_FORMAT( CURDATE( ) , '%Y%m' )

上一月

SELECT * FROM 表名 WHERE PERIOD_DIFF( date_format( now( ) , '%Y%m' ) , date_format( 时间字段名, '%Y%m' ) ) =1


复制代码

在presto中使用时间格式,须要明确写出关键字timestamp,好比:

select supplier,count(id) 
from xxx_table 
where sendtime >= timestamp '2019-06-01' 

复制代码

参考资料:

4.3 其余经常使用的函数

这里我简单整理一下我最近用过函数:

length  --计算字符串长度
concat  --链接两个字符串
substring -- 截取字符串
count   -- 统计数量
max   -- 最大
min   -- 最小
sum   -- 合计
floor/ceil  --...数学函数

复制代码

再来分享一下最近遇到的一个需求,如今有的数据以下:

【Java3y简单】快乐学习
【Java3y简单】快乐学习渣渣
【Java3y通俗易懂】简单学
【Java3y通俗易懂】简单学芭芭拉
【Java3y平易近人】无聊学
【Java3y初学者】枯燥学
【Java3y初学者】枯燥学呱呱
【Java3y大数据】欣慰学
【Java3y学习】巴拉巴拉学
【Java3y学习】巴拉巴拉学哈哈
【Java3y好】雨女无瓜学

复制代码

如今我统计出【】括号里边出现的频次,好比说:Java3y通俗易懂出现的频次是多少。当时一直都没想到好的思路,都快要搜“SQL 正则表达式 快速入门”了,请教了一下同事,同事很快就写出来了:

select substring_index(left(title , INSTR(title , '】') -1 ) , '【',-1) 
FROM `xxx_table`

复制代码

哇~,awesome

最后

乐于输出干货的Java技术公众号:Java3y。公众号内有200多篇原创技术文章、海量视频资源、精美脑图,关注便可获取!

转发到朋友圈是对我最大的支持!

以为个人文章写得不错,点

相关文章
相关标签/搜索