SQL语法

关键字总览

1.什么是DQL?

数据库语言主要分为查询语言DQL、数据操纵语言DML、数据定义语言DDL、数据控制语言DCL
查询语言DQL:
SELECT <字段名表> FROM <表或视图名> WHERE <查询条件>
数据操纵语言DML:
1)插入:INSERT
  insert into tmp (medid,searchid) values (12345,54321);
  2)更新:UPDATE
  update tmp set searchid=’1’ where medid=’12345’;
  3)删除:DELETE
  delete from tmp where medid=’12345’;
数据定义语言DDL
数据定义语言DDL用来创建数据库中的各种对象—–表、视图、索引、同义词、聚簇等如:
CREATE TABLE/VIEW/INDEX/SYN/CLUSTER(表 视图 索引 同义词 簇)
数据控制语言DCL
数据控制语言DCL用来授予或回收访问数据库的某种特权,并控制数据库操纵事务发生的时间及效果,对数据库实行监视等。如:
  1) GRANT:授权。
  2) REVOKE:撤销授权。

2.DQL表达式有哪些

子句描述子句描述
select要返回的列和表达式like模糊匹配
from从中检索数据的表between and连续数值范围限定
left join返回左表所有行where后面增加筛选条件
right join返回右表所有行逻辑运算符and、or、not
inner join返回两表交集比较运算符=、<>、<、>、!=
join笛卡尔积,不需要on主键in非连续值筛选
fulljoin所有集合,包含重复数据空值筛选is null、is ‘’、is not null
on关联条件,用join是才用if(expr,1,0)条件判断
case when条件判断group by分组函数
having对分组后的结果进行条件过滤,与group byunion表纵向拼接
order by排序函数desc倒序limit限制输出行数

在这里插入图片描述

3.编写&执行顺序

编写顺序
在这里插入图片描述
执行顺序
在这里插入图片描述

常用的函数

数据去重
方法一:使用distinct,后面全部条件相同才会去重
方法二:group by 去重,使用分组后,字段需要添加聚合函数max()min()等
方法三:窗口函数row_number(),使用distinct去重

聚合函数
聚合函数有count()、max()、min()、sum()、avg(),如果select 后字段里没有非聚合字段,可以不使用group by

范围查询
连续值使用between num1 and num2 包含两个边界数值
非连续使用in (‘a’,‘b’,‘v’)

Json数据处理
mysql获取key中的value

SELECT JSON_EXTRACT(`测试表`.jason, '$.EngSpd') FROM 测试表 WHERE`测试表`.jason LIKE '%EngSpd%' AND `测试表`.jason !='NULL'

mysql获取json数组中的value

SELECT `测试表`.jason,JSON_EXTRACT(`测试表`.jason, '$.EngSpd') ,JSON_EXTRACT(`测试表`.jason, '$.EngSpd[2]') FROM 测试表 WHERE`测试表`.jason LIKE '%EngSpd%' AND `测试表`.jason !='NULL'
key值后加[1]位置即可

Hive获取key中的value

get_json_object(ten.data_args, '$.value') !='-1.0'
获取复杂嵌套json,一层一层提取即可
get_json_object(get_json_object(get_json_object(get_json_object(data_args,'$.nlu_result'),'$.sys_light_string'),'$.nlu_result[0]'),'$.domain'))

窗口函数
窗口函数

条件筛选

select a.StudentID,
 (case a.IsUse 
 when '0' then '未在线' 
 when '1' then '在线' 
 else '未上传'
 end) as 在线情况
from StudentBindPaperTypeEntity as a
必须要包含end

CASE WHEN minute(time_stamp) >=30 THEN hour(time_stamp) + 1
                    WHEN minute(time_stamp) <30 THEN hour(time_stamp)
               END AS hr       
#case要判断的字段,when直接比较值
case mod(row_number() over(partition by uid, date_sub(sign_dt, interval rn day) order by sign_dt), 7)          when 3 then 3 -- 2+1 额外领 2            when 0 then 7 -- 6+1 额外领 6          else 1      end) as daily_coin
if(EXPR,A,B)--符合条件为A,不符合为B

格式转换
hive时间戳转化为北京时间,需要注意转换成北京东八时区,特别是计算早高峰晚高峰避免错误

from_utc_timestamp(from_unixtime(cast(cast(data_stamp_time as BIGINT)/1000 as BIGINT)),'PRC')acquisition_time1

mysql任意时间格式转换

to_timestamp("substring"(report_tid, 0, 13), 'YYMMDDHH24MISS')

mysql date_format(),后面自定义日期格式

 select      concat(year(submit_time),substring(submit_time,6,2)) as month
	    ,round(count(distinct uid,date_format(submit_time,'%y%m%d'))/count(distinct uid),2) as avg_active_days
                       ,count(distinct uid) as  mau
            from        exam_record
            where       submit_time is not null
                        and year(submit_time)>2020
            group by    month

hive 取当前日期月份最后一天,便于计算当月天数

SELECT vin
     ,last_day(from_utc_timestamp(from_unixtime(cast(cast(data_stamp_time AS BIGINT)/1000 AS BIGINT)),'PRC'))
FROM hdfs.ods_hu_track_hi
where dt='2022-02-16'

hive字符串转自定义日期格式

from_unixtime( unix_timestamp(substr(tid,1,12),'yyMMddHHmmss'),'yyyy-MM-dd HH:mm:ss')

日期格式处理
求日期差 DATEDIFF(max_time,start_time)<=29 2021-10-01 10:00:00-2021-10-01 10:00:20
日期取月份

日期取间隔
使用date_sub函数(Subtract减去,还有add增加)

date_sub('2019-07-27', interval 30 day) 取前三十天
date_sub('2019-07-27', 2)日期减少2
hive> select date_sub('2019-06-25',-2);2019-06-27

mysql 日期求差和秒求差

date_add((select max(end_time) from tb_user_video_log),interval -29 day)  计算小于29天
timestampdiff(second,start_time,end_time)  计算日期的秒数差

四舍五入
保留小数

 round(cast(amap_lat AS FLOAT),2)amap_lat

向下取整

select floor(103.56) from dual ---103

类型转换

cast(str as int/float)  --str如果是带小数点,则转成float,否则报错

字符串截取函数

select Left(‘Welcome to China!,7)
返回:Welcome
select Right(‘Welcome to China!,6)
返回:China!
select SubString(‘Welcome to China!,9,2)
返回:to

注意:substring(‘字段’,起始,长度)最后一位为长度
另外substring_index函数也可以字符串切割,包含三个参数(‘字段’,‘切割方式’,从哪个位置切割)
从哪个位置切割1正向,2是前两个,-1是反向
如何取中间,使用两个sunbtring_index方法

count()
count(1)和count(*)会记录null记录数,count(列名)会过滤掉空值

传参
可以使用’${ }'进行传参,比如日期范围

WHERE dt>'${dt}'
and   dt<'${dt}'

union&union all
union主要实现表与表之间的纵向连接,需要保证字段数量一致,区别如下:
union all执行速度大于union
union all不会对重复数据去重,union会去除重复数据

字段合并函数
实现横向多个字段合并concat(str1,str2,)
实现纵向多行某个字段合并GROUP_CANCAT(字段 SEPARATOR ‘,’),必须与group by搭配
hive 默认间隔是‘,’直接distinct 即可

limit任意行取值

limit 25 --取值2到5行,最好进行排序
limit 99999 offset 0;99999条,从第0行开始

join
无论是left join还是inner join 如果一对多,左表会生成多行,而不是左表行数不变
join分为等值join和不等值join
不等值join可以使用
在这里插入图片描述
或是模糊查询
在这里插入图片描述
hivesql建议使用locate函数,用户模糊查询
字符串比较
字符串日期和数据可以直接比较,因为比较的是每位的ascII码

group by 1
group by 1代表select 后面第一列进行分组

regexp正则表达式

app_name regexp 'wey|haval|tank|ora|Poer'  --正则表达式或关系,类似 app_name in ('wey','haval')

trunc
trunc(number,x)对数字进行截取

select TRUNC(15.79,1) from dual;TRUNC(15.79,1)
--------------
15.7

trunc (date,‘DD’)DD代表今天0点 d代表本周第一天,mm代表本月第一天,hh代表小时
trunc使用

GROUP_CONCAT函数+SPLIT_PART函数
实现多行json的拼接,SPLIT_PART进行数据的切分SPLIT_PART(col,‘sep’,N)设置分隔符和切割第几个

lateral view+explode
实现列转多行,将原本一行的数据拆分成多行的虚拟表,再与原表进行笛卡尔积,从而形成明细表
split将一行按照分隔符拆分成数组

select col_A,col_B,tmp_table.tmp_col 
from test_table 
lateral view explode(split(col_C,'分隔符')) tmp_table as tmp_col
where partition_name='xxx';

编码原则和规范

阿里规范
编码原则:
1.执行速度优先
2.SQL关键字、保留字采用全大写或小写
3.增加适当的注释
4.四个空格为一个缩进量,缩进为倍数
5.对应的括号在同一列的位置上
6.禁止select*操作,指定列名
编码规范
1.代码头部增加主题、功能描述、作者和日期等信息


**所属主题
**功能描述
**创建者
**创建日期
**修改日志
**修改人


2.select、from、groupby、having、orderby在同一行
3.select第一行带字段,后面依次换行,逗号在前,as并排
4.算数和逻辑运算符前面加空格
5.case语句 when并排,必须增加else
6.子查询规范,后面可以用a,b,c,d,e或s1,s2,s3,s4,括号在同一列,子查询缩进一个空格
7.每条语句进行注释,跟在字段后面或者在前面
在这里插入图片描述

SQL优化

待定

案例

计算连续两天签到的数量

    select count(distinct user_id)
    from (
        select  user_id,mid_date,count(1)  as cnt
        from    (
                select *,date_sub(dt,num) as mid_date--日期减去排序号,相同则代表连续
                from    
                        (
                        select user_id,dt,row_number() over (partition by user_id order by dt) as num  --分用户增加排序数字
                        from   dwd_point_detail_di
                        where  dt<='${dt}' 
                        and port='HJ0002'
                        )a
                )b
        group by user_id,mid_date)c
        where cnt=2--只有连续天数数量为2的保留

计算每天的活跃留存

select x.dt
,count(distinct x.device_id) dau
,count(distinct case when datediff(x.dt2,x.dt)=1 
then x.device_id2 end) day__2
,count(distinct case when datediff(x.dt2,x.dt)=2
then x.device_id2 end) day__3
,count(distinct case when datediff(x.dt2,x.dt)=3
then x.device_id2 end) day__4
,count(distinct case when datediff(x.dt2,x.dt)=4
then x.device_id2 end) day__5
,count(distinct case when datediff(x.dt2,x.dt)=5
then x.device_id2 end) day__6
,count(distinct case when datediff(x.dt2,x.dt)=6
then x.device_id2 end) day__7
from(
    select k1.dt,k1.device_id,k2.dt as dt2,k2.device_id as device_id2
    from 
        (--统计日期当天的用户id
        SELECT distinct left(cast(from_utc_timestamp(from_unixtime(cast(left(client_time,10) as BIGINT)),'PRC')as string),7) as 'dt',device_id  FROM *
        where app_name like '%${brand}%'
        and dt between '${start}' and '${end}'
        and left(cast(from_utc_timestamp(from_unixtime(cast(left(client_time,10) as BIGINT)),'PRC')as string),10) between '${start}' and '${end}'
        )k1
    left join
        (--之后又来的用户id
        SELECT distinct left(cast(from_utc_timestamp(from_unixtime(cast(left(client_time,10) as BIGINT)),'PRC')as string),10) as 'dt',device_id  FROM hdfs.ods_mb_track 
        where app_name like '%${brand}%' 
        and dt between '${start}' and '${end}'
        and left(cast(from_utc_timestamp(from_unixtime(cast(left(client_time,10) as BIGINT)),'PRC')as string),10) between '${start}' and '${end}'
        )k2 on k1.dt<k2.dt and k1.device_id = k2.device_id --匹配条件:前后id相同,dt晚于统计日dt
    )x
 group by x.dt order by x.dt;

①确定时间范围start_time 和end_time
②将每天和比它大的日期+设备id left join进行做差,通过时间差判断属于几天活跃,最终得到结果(倒三角形结果)

根据用户活跃间隔分析用户等级
用户等级标准简化为:忠实用户(近7天活跃过且非新晋用户)、新晋用户(近7天新增)、沉睡用户(近7天未活跃但更早前活跃过)、流失用户(近30天未活跃但更早前活跃过)
SQL165 统计活跃间隔对用户分级结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值