SQL系列(三)SQL使用的旁枝末节

SQL系列(三)SQL使用的旁枝末节

首先,来揭晓上期的答案。方法不唯一,符合结果即可~

with temp as 
    (
        select 2 as st,5 as en
        union all
        select 11 as st,9 as en
    )

select
    st
    ,en
    ,collect_list(numbers_end) as result -- 得到等差数组
from
    (
        select
            st
            ,en
            ,if(st<en,int(numbers+rn),int(numbers-rn)) as numbers_end -- 构造等差数值
        from
            (
                select
                    st
                    ,en
                    ,numbers
                    ,row_number() over(partition by st order by st) -1 as rn -- 构造排序字段辅助计算
                from
                    (-- 构造起始差长度+1的重复序列
                        select
                            st
                            ,en
                            ,regexp_extract(repeat(concat(st,','),int(abs(en-st)+1)),'(.*),',1) as number_repeat_list
                        from
                            temp
                    )a 
                lateral view explode(split(number_repeat_list,',')) t as numbers -- 将重复序列展开成多行
            )a
    )a
group by
    st
    ,en

虽然日常中使用最多的是查询,但在数字基建中,增删改也是必不可少的。

Hive的DDL

创建表

-- 创建表模版
use temp;
CREATE TABLE hh_teachr_price
    (
        teacherid string comment "教师ID"
        ,task_type string comment "任务类型"
        ,price string comment "基础单价"
    )
PARTITIONED BY (`dt` string) -- 含分区
ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
WITH SERDEPROPERTIES (
'field.delim'='\t', -- 字段分隔符
'serialization.format'='\t')
STORED AS INPUTFORMAT
'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
;

增删改"插"

-- 新增字段 -- 含分区的表需加上关键字CASCADE,联级改变历史分区文件结构
alter table temp.hh_teachr_price add columns(type string comment '题型', course string comment '科目') CASCADE;

-- 删除字段
alter table temp.hh_teachr_price replace columns (teacherid string, task_type string); -- 删除price

-- 修改列名
alter table temp.hh_teachr_price CHANGE COLUMN task_type task_type_new string comment '任务特征';
-- 修改注释
alter table temp.hh_teachr_price CHANGE COLUMN task_type task_type string comment '任务特征2';
-- 修改分隔符类型
alter table temp.hh_teachr_price set serdeproperties('field.delim'=',', 'serialization.format'=',');

-- 插入数据
insert overwrite table temp.hh_teachr_price partition (dt='${date}') -- 覆盖写入
select ...

insert into table temp.hh_teachr_price partition (dt='${date}') -- 追加写入
select ...

MySQL的DDL

创建表

-- 创建表模版
use temp;
CREATE TABLE `question_nums`
    (
        `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键'
        ,`dt` varchar(30) NOT NULL DEFAULT 'total_count' COMMENT '日期'
        ,`phase` varchar(30) NOT NULL DEFAULT 'total_count' COMMENT '学段'
        ,`nums` int(30) NOT NULL DEFAULT '0' COMMENT '数量'

        ,`dbctime` datetime(3) DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间'
        ,`dbutime` datetime(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间'

        ,PRIMARY KEY (`id`)
        ,UNIQUE KEY `u_key` (`dt`,`phase`)
    ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT '题目数量'

增删改

-- 合并为一条语句
alter table question_nums
add column `language` varchar(30) not null default 'total_count' comment '语言' -- 增加维度
,add column `new_nums` int(30) not null default '0' comment '新增数量' -- 增加度量
,drop column `new_nums` -- 删除字段
,modify column `nums` decimal(10,1) not null default '0' COMMENT '数量' -- 只修改字段类型
,change `nums` `nums_new` int(30) not null default '0' COMMENT '数量' -- 修改字段名称和类型

,drop index `u_key` -- 删除索引
,add unique key `u_key` (`dt`,`phase`,`language`); -- 增加索引

Hive其他操作

服务器查看hdfs文件

# hdfs dfs 与 hadoop fs 用法相通
hdfs dfs -ls 列出路径下的所有文件和文件夹(统计分区数量)
hdfs dfs -cat 查看文件中的内容
hdfs dfs -text 查看文件中的内容
hdfs dfs -text /app/20190909/* |grep channel_id=14764618 正则查找
hdfs dfs -text /app/20190909/* | head[tail] -n 5 展示前[后]5行
hdfs dfs -du -s -h /app/20190909/ 整体文件大小
hdfs dfs -du -s -h /app/20190909/* 各分区文件大小
hdfs dfs -cat /app/20190909/* | wc -l 查看文件行数

Hive参数设置

-- 参数设置
set hive.new.job.grouping.set.cardinality =256; -- 维度组合数2的n次方
set mapreduce.reduce.memory.mb = 8192; -- reduce大小
set mapreduce.map.memory.mb = 8192; -- map大小
set hive.exec.parallel=true; -- 并发
set hive.strict.checks.large.query = false; -- 非严格限制
set hive.mapred.mode = nonstrict; -- 非严格限制
set hive.cli.print.header=true; -- 显示列名
set hive.resultset.use.unique.column.names=false; -- 不显示库表前缀

这里重点说一下严格模式和非严格模式:Hive在严格模式下查询时,需指定分区(查询分区表时),排序后需增加limit限制,不支持笛卡尔积查询。防止误操作等造成的资源浪费。

  • 在严格模式下需指定分区,避免全盘扫面带来的浪费

    分区简单理解就是文件夹,例如按照日期建立多个文件夹,每个日期的数据存在相应的文件夹下。此时的分区字段就是日期。例如:

select
	*
from
	temp1
where
	dt = current_date(dt, -1) -- 指定分区为昨日
  • 在严格模式下需限制排序数量,避免全局排序造成的浪费

    如果排序完后要获取所有数据,可以将limit设置很大,例如:

    select
    	*
    from
    	temp1
    where
    	dt = current_date(dt, -1) -- 指定分区为昨日
    order by
    	age
    limit 100000000 -- 增加limit限制
    
  • 在严格模式下不支持笛卡尔积,主要防止分析师的不当操作,造成资源大量浪费

    可以增加关联字段代替笛卡尔积查询方式,如果还会报错,可以设置参数开启非严格模式,例如:

    -- 开启非严格模式 -- 理论上不开启下述代码也能正常运行
    set hive.strict.checks.large.query = false;
    set hive.mapred.mode = nonstrict;
    
    select
        col1
        ,col2
    from
        (
            select
                1 as connect
                ,col1
            from
                tamp1
        )t1 
    left join
        (
            select
                1 as connect
                ,col2
            from
                tamp1
        )t2 on t1.connect=t2.connect -- 1关联1形成笛卡尔积
    

客户端交互命令

# -e 执行sql语句
hive -e "select * from temp.hh_teachr_price limit 100;"
# -f 执行sql脚本
hive -f /app/mydata/hh_teachr_price.sql

# 服务器cli上输出文件
hive -e"set hive.cli.print.header=true; -- 显示列名
set hive.resultset.use.unique.column.names=false; -- 不显示库表前缀

select * from temp.hh_teachr_price limit 100;" | sed 's/[\t]/,/g' >hh_teachr_price.csv


# hive集群输出文件 无法带标题
set hive.cli.print.header=true; -- 显示列名
set hive.resultset.use.unique.column.names=false; -- 不显示库表前缀

insert overwrite local directory '/home/data/hh_teachr_price' 
row format delimited fields terminated by ',' 
select * from temp.hh_teachr_price limit 100;

日常爬坑

  1. 长整型字段与字符串字段关联,两个默认会转为double型,有时会因为超出长度结尾数字变为0造成匹配错误(一对多)。可以将长整型字段转化为字符串再关联。
-- 结尾溢出造成错误匹配上了
select
    a.id
    ,b.id
from
    (
        select 
      		bigint(190000000002778025) as id
    )a
left join
    (
        select '190000000002778023' as id
    )b on a.id=b.id
  1. 非数值型字符串与数字/数值型字符串比较的区别
select 
	-- 非数值型字符串与数字比较,会造成结果为null
    'abc' != 2 as a -- null
    ,'' != 2 as c -- null
    -- 将数字转为数值型字符串即可
    ,'abc' != '2' as b -- true
    ,'' != '2' as d -- true
  1. 字段含有null值,会导致explode丢失数据
-- 因为null造成A类型的数据丢失
select
    ids
    ,id
    ,dtype
from
    (
        select 
            null as ids
            ,'A' as dtype

        union all 

        select
            '3,4,6' as ids
            ,'B' as dtype
    )a 
lateral view explode(split(ids,',')) t as id

总结

至此,SQL系列已经全部结束,但是需求是无穷的。道阻且长,且行且珍惜~

共勉~

#数据分析教程##数据分析师工作#
数据分析实用手册 文章被收录于专栏

微信知乎搜索HsuHeinrich,第一时间更新~ 最真实的数据分析教程,SQL、Python、Tableau、Excel、数据基建、BI报表、埋点、专题分析、数据挖掘、A/B试验。日常分析师涉及的方方面面,这里都有~

全部评论

相关推荐

11-17 11:15
门头沟学院 Java
金山办公终于发offer了,但薪资和平台都不如已有的offer打算拒了,A不了薪资,不满意直接拒了,留给需要的人嘿嘿嘿时间线:10.14线下一面&nbsp;,10.23线上二面,下午发测评,11月1日HR面,11月14日电话谈薪,11月17日直接发offer
star__plat...:好兄弟干的好啊,解气。金山第一次笔难度高的离谱,第二次简单的离谱全A了,用人部门筛选中估计最后还是要挂我,就这今早智联招聘还给我发信息让我投
offer帮选
点赞 评论 收藏
分享
Java转测开第一人:这种就是饼 把应届当廉价劳动力用完然后丢掉
你觉得今年秋招难吗
点赞 评论 收藏
分享
10-19 10:28
已编辑
成都理工大学 后端工程师
团孝子已上线feeling:面了很多家公司,能感受到目前只有小公司+外包喜欢问八股。大厂虽然也问八股,但是是从实习、项目中进行提问,并且大厂会问很深,面试官也会对你的回答进行思考➕追问,所以准备大厂面试前一定要备好相关资料。对于算法,我做的是codetop前100+力扣hot100+力扣高频150,面试中实感hot100就足够,基本上只要是hot100就秒答。对于项目和八股,我做的也是烂大街的星球项目,八股则是看小林和问ai,自己也写了很多技术博客和画了很多思维导图,并且自己也尝试用嘴巴说出来,不只停留于纸面。运气也很重要,必须要让面试官/HR看到简历才行,所以建议投递时间是下午两点。tl:第一岗位9.9&nbsp;投递9.10&nbsp;一面(一面评价:最近见过最强的大三,结束五分钟后约二面,都晚上九点了不下班吗)9.11&nbsp;二面(三道算法a出两道,反问评价:经验不够等横向,我实习生要啥经验)9.21挂(实习时间过短+其他原因,想要一年实习的,为什么不招个正职)第二岗位10.10投递10.11约面(主管打电话,说看到我之前投递记录了想要我挂qa职进去干后端,同意)10.14&nbsp;一面(无八股,主动说确实很强,意愿很强)10.16&nbsp;oc其余,友邦,东软,东华,惠择,用友oc已拒京东测开一面挂(投后端被测开捞)腾讯测试已拒(投后端被测开捞)ps:表扬惠择的主管面,没怎么问技术(可能是一面面试官沟通过了),全程一起讲大道理,解答了心中很多疑惑,也告诉我以面试官角度来看怎么选候选人,如果可以下次一定选惠择
HeaoDng:美团好像可以触发一面通
点赞 评论 收藏
分享
评论
1
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务