转载:Hive sql语句必练50题-入门到精通(1)

原始链接:https://blog.csdn.net/Thomson617/article/details/83212338

里面有一些错误,我改过来了。错误的地方比如:列名用中文。

列名的定义为string类型,使用时用int类型,这个在hive里能执行成功,因为是隐式转换。有些隐式转换会引发全表搜索,不推荐这样做。我建议使用时采用定义的类型。这是类型转换的解释:

如果查询出来的数据类型和插入表格对应的列数据类型不一致,将会进行转换,但是不能保证转换一定成功,比如如果查询出来的数据类型为int,插入表格对应的列类型为string,可以通过转换将int类型转换为string类型;但是如果查询出来的数据类型为string,插入表格对应的列类型为int,转换过程可能出现错误,因为字母就不可以转换为int,转换失败的数据将会为NULL。

 

错误那么明显,在hive里根本就执行不过去。我怀疑是原文作者故意挖坑。所以懒虫们在看别人写的文章的时候,最好自己搭个环境实际动手练一练,别一天到晚拿来主义伸手党啦。

如果列名是唯一的,原作者喜欢直接写列名,省略表名。通篇都是这么做的。我的习惯是不管列名是不是唯一的,都表名.列名。也建议大家采用表名.列名的习惯。因为数据库的表有可能会因为工作需要而修改表的结构。由于通篇都是这样的,我就懒得改了。

还有就是原文作者没写的东东,有时也很重要。比如hive sql50题,至少要在纸上画画ER图,搞清楚各个表的主键、外键、表与表之间的关系。

 

Hive sql语句必练50题-入门到精通(1)

hive学习之经典sql 50题 hive版

建表:


   
   
  1. create table student(s_id string,s_name string,s_birth string,s_sex string) row format delimited fields terminated by '\t';
  2. create table course(c_id string,c_name string,t_id string) row format delimited fields terminated by '\t';
  3. create table teacher(t_id string,t_name string) row format delimited fields terminated by '\t';
  4. create table score(s_id string,c_id string,s_score int) row format delimited fields terminated by '\t';

生成数据

vi /export/data/hivedatas/student.csv

在notepad++里,一次编辑多行:alt+鼠标左键拖动

01 赵雷 1990-01-01 男
02 钱电 1990-12-21 男
03 孙风 1990-05-20 男
04 李云 1990-08-06 男
05 周梅 1991-12-01 女
06 吴兰 1992-03-01 女
07 郑竹 1989-07-01 女
08 王菊 1990-01-20 女

vi /export/data/hivedatas/course.csv

01 语文 02
02 数学 01
03 英语 03

vi /export/data/hivedatas/teacher.csv

01 张三
02 李四
03 王五

vi /export/data/hivedatas/score.csv

01 01 80
01 02 90
01 03 99
02 01 70
02 02 60
02 03 80
03 01 80
03 02 80
03 03 80
04 01 50
04 02 30
04 03 20
05 01 76
05 02 87
06 01 31
06 03 34
07 02 89
07 03 98

导数据到hive


   
   
  1. load data local inpath '/export/data/hivedatas/student.csv' into table student;
  2. load data local inpath '/export/data/hivedatas/course.csv' into table course;
  3. load data local inpath '/export/data/hivedatas/teacher.csv' into table teacher;
  4. load data local inpath '/export/data/hivedatas/score.csv' into table score;

–注:–hive查询语法

字段不能写成中文


   
   
  1. SELECT [ALL | DISTINCT] select_expr, select_expr, ...
  2. FROM table_reference
  3. [ WHERE where_condition]
  4. [ GROUP BY col_list [HAVING condition]]
  5. [CLUSTER BY col_list
  6. | [DISTRIBUTE BY col_list] [SORT BY| ORDER BY col_list]
  7. ]
  8. [LIMIT number]

– 1、查询"01"课程比"02"课程成绩高的学生的信息及课程分数:


   
   
  1. select student.*,a.s_score as 01_score,b.s_score as 02_score
  2. from student
  3. join score a on student.s_id=a.s_id and a.c_id= '01'
  4. left join score b on student.s_id=b.s_id and b.c_id= '02'
  5. where a.s_score>b.s_score;

–答案2


   
   
  1. select student.*,a.s_score as 01_score,b.s_score as 02_score
  2. from student
  3. join score a on a.c_id= '01'
  4. join score b on b.c_id= '02'
  5. where a.s_id=student.s_id and b.s_id=student.s_id and a.s_score>b.s_score;

– 2、查询"01"课程比"02"课程成绩低的学生的信息及课程分数:


   
   
  1. select student.*,a.s_score as 01_score,b.s_score as 02_score
  2. from student
  3. join score a on student.s_id=a.s_id and a.c_id= '01'
  4. left join score b on student.s_id=b.s_id and b.c_id= '02'
  5. where a.s_score<b.s_score;

–答案2


   
   
  1. select student.*,a.s_score as 01_score,b.s_score as 02_score
  2. from student
  3. join score a on a.c_id= '01'
  4. join score b on b.c_id= '02'
  5. where a.s_id=student.s_id and b.s_id=student.s_id and a.s_score<b.s_score;

– 3、查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩:


   
   
  1. select student.s_id,student.s_name,tmp.avgScore from student
  2. join (
  3. select score.s_id,round(avg(score.s_score), 1) as avgScore
  4. from score group by s_id) as tmp
  5. on tmp.avgScore>= 60
  6. where student.s_id = tmp.s_id

–答案2


   
   
  1. select student.s_id,student.s_name,round(avg (score.s_score), 1) as avgScore from student
  2. join score on student.s_id = score.s_id
  3. group by student.s_id,student. s_name
  4. having avg (score.s_score) >= 60;

– 4、查询平均成绩小于60分的同学的学生编号和学生姓名和平均成绩:
– (包括有成绩的和无成绩的)


   
   
  1. select student.s_id,student.s_name,tmp.avgScore from student
  2. join (
  3. select score.s_id,round(avg(score.s_score), 1) as avgScore from score group by s_id) as tmp
  4. on tmp.avgScore < 60
  5. where student.s_id=tmp.s_id
  6. union all
  7. select s2.s_id,s2.s_name, 0 as avgScore from student s2
  8. where s2.s_id not in
  9. ( select distinct sc2.s_id from score sc2);

–答案2


   
   
  1. select score.s_id,student.s_name,round( avg (score.s_score), 1) as avgScore from student
  2. inner join score on student.s_id =score.s_id
  3. group by score.s_id,student.s_name
  4. having avg (score.s_score) < 60
  5. union all
  6. select s2.s_id,s2.s_name, 0 as avgScore from student s2
  7. where s2.s_id not in
  8. ( select distinct sc2.s_id from score sc2);

– 5、查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩:


   
   
  1. select student.s_id,student.s_name,(count(score.c_id) ) as total_count,sum(score.s_score) as total_score
  2. from student
  3. left join score on student.s_id=score.s_id
  4. group by student.s_id,student.s_name ;

– 6、查询"李"姓老师的数量:

select t_name,count(1) from teacher  where t_name like '李%' group by t_name;

   
   

– 7、查询学过"张三"老师授课的同学的信息:


   
   
  1. select student.* from student
  2. join score on student.s_id =score.s_id
  3. join course on course.c_id=score.c_id
  4. join teacher on course.t_id=teacher.t_id and t_name= '张三';

– 8、查询没学过"张三"老师授课的同学的信息:


   
   
  1. select student.* from student
  2. left join (select s_id from score
  3. join course on course.c_id=score.c_id
  4. join teacher on course.t_id=teacher.t_id and t_name='张三')tmp
  5. on student.s_id =tmp.s_id
  6. where tmp.s_id is null;

– 9、查询学过编号为"01"并且也学过编号为"02"的课程的同学的信息:


   
   
  1. select * from student
  2. join ( select s_id from score where c_id = '01' )tmp1
  3. on student.s_id=tmp1.s_id
  4. join ( select s_id from score where c_id = '02' )tmp2
  5. on student.s_id=tmp2.s_id;

– 10、查询学过编号为"01"但是没有学过编号为"02"的课程的同学的信息:


   
   
  1. select student.* from student
  2. join ( select s_id from score where c_id ='01' )tmp1
  3. on student.s_id=tmp1. s_id
  4. left join (select s_id from score where c_id ='02' )tmp2
  5. on student.s_id =tmp2.s_id
  6. where tmp2.s_id is null;

– 11、查询没有学全所有课程的同学的信息:
–先查询出课程的总数量

   select count(1) from course;

   
   

–再查询所需结果


   
   
  1. select student. * from student
  2. left join(
  3. select s_id
  4. from score
  5. group by s_id
  6. having count(c_id) = 3)tmp
  7. on student.s_id =tmp.s_id
  8. where tmp.s_id is null;

–方法二(一步到位):


   
   
  1. select student. * from student
  2. join ( select count(c_id)num1 from course)tmp1
  3. left join(
  4. select s_id, count(c_id)num2
  5. from score group by s_id)tmp2
  6. on student.s_id =tmp2.s_id and tmp1.num1 =tmp2.num2
  7. where tmp2.s_id is null;

– 12、查询至少有一门课与学号为"01"的同学所学相同的同学的信息:

group by里的字段必须在select里。如果写成select *,那么groupy by必须把*所在的表的所有字段col1, col2,...,col_n逐一写出来;如果写成select col_1, col_2,那么group by col_1就可以了。


   
   
  1. select student.* from student
  2. join ( select c_id from score where score.s_id= '01')tmp1
  3. join ( select s_id,c_id from score)tmp2
  4. on tmp1.c_id =tmp2.c_id and student.s_id =tmp2.s_id
  5. where student.s_id not in( '01')
  6. group by student.s_id,s_name,s_birth,s_sex;

– 13、查询和"01"号的同学学习的课程完全相同的其他同学的信息:
–备注:hive不支持group_concat方法,可用 concat_ws(’|’, collect_set(str)) 实现

concat_ws(separator, [string | array(string)]+) - returns the concatenation of the strings separated by the separator. 合并字符串,字符串的分隔符为separator指定的字符。

collect_set(x) - Returns a set of objects with duplicate elements eliminated返回一组不重复的对象,重复的元素已被删掉


   
   
  1. select student.*,tmp1. course_id from student
  2. join ( select s_id ,concat_ws('|', collect_set(c_id)) course_id from score
  3. group by s_id having s_id not in ( '01'))tmp1
  4. on student.s_id = tmp1. s_id
  5. join ( select concat_ws('|', collect_set(c_id)) course_id2
  6. from score where s_id= '01')tmp2
  7. on tmp1.course_id = tmp2.course_id2;

– 14、查询没学过"张三"老师讲授的任一门课程的学生姓名:


   
   
  1. select student.* from student
  2. left join (select s_id from score
  3. join (select c_id from course join teacher on course.t_id=teacher.t_id and t_name='张三')tmp2
  4. on score.c_id=tmp2.c_id )tmp
  5. on student.s_id = tmp.s_id
  6. where tmp.s_id is null;

– 15、查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩:


   
   
  1. select student.s_id,student.s_name,tmp.avg_score from student
  2. inner join ( select s_id from score
  3. where s_score < 60
  4. group by score.s_id having count(s_id) > 1)tmp2
  5. on student.s_id = tmp2.s_id
  6. left join (
  7. select s_id,round( AVG (score.s_score)) avg_score
  8. from score group by s_id)tmp
  9. on tmp.s_id =student.s_id;

– 16、检索"01"课程分数小于60,按分数降序排列的学生信息:


   
   
  1. select student. *,s_score from student,score
  2. where student.s_id =score.s_id and s_score < 60 and c_id = '01'
  3. order by s_score desc;

– 17、按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩:


   
   
  1. select a.s_id,tmp1.s_score as chinese,tmp2.s_score as math,tmp3.s_score as english,
  2. round(avg (a.s_score), 2) as avgScore
  3. from score a
  4. left join (select s_id,s_score from score s1 where c_id='01')tmp1 on tmp1.s_id=a. s_id
  5. left join (select s_id,s_score from score s2 where c_id='02')tmp2 on tmp2.s_id=a. s_id
  6. left join (select s_id,s_score from score s3 where c_id='03')tmp3 on tmp3.s_id=a.s_id
  7. group by a.s_id,tmp1.s_score,tmp2.s_score,tmp3.s_score order by avgScore desc;

– 18.查询各科成绩最高分、最低分和平均分:以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率:
–及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90


   
   
  1. select course.c_id,course.c_name,tmp.maxScore,tmp.minScore,tmp.avgScore,tmp.passRate,tmp.moderate,tmp.goodRate,tmp.excellentRates from course
  2. join( select c_id, max(s_score) as maxScore, min(s_score) as minScore,
  3. round( avg(s_score), 2) avgScore,
  4. round( sum( case when s_score >= 60 then 1 else 0 end) / count(c_id), 2)passRate,
  5. round( sum( case when s_score >= 60 and s_score < 70 then 1 else 0 end) / count(c_id), 2) moderate,
  6. round( sum( case when s_score >= 70 and s_score < 80 then 1 else 0 end) / count(c_id), 2) goodRate,
  7. round( sum( case when s_score >= 80 and s_score < 90 then 1 else 0 end) / count(c_id), 2) excellentRates
  8. from score group by c_id)tmp on tmp.c_id =course.c_id;

– 19、按各科成绩进行排序,并显示排名:
– row_number() over()分组排序功能(mysql没有该方法)


   
   
  1. select s1. *, row_number() over( order by s1.s_score desc) Ranking
  2. from score s1 where s1.c_id = '01' order by Ranking asc
  3. union all select s2. *, row_number() over( order by s2.s_score desc) Ranking
  4. from score s2 where s2.c_id = '02' order by Ranking asc
  5. union all select s3. *, row_number() over( order by s3.s_score desc) Ranking
  6. from score s3 where s3.c_id = '03' order by Ranking asc;

– 20、查询学生的总成绩并进行排名:


   
   
  1. select score.s_id,s_name, sum(s_score) sumscore, row_number() over( order by sum(s_score) desc) Ranking
  2. from score ,student
  3. where score.s_id =student.s_id
  4. group by score.s_id,s_name order by sumscore desc;

后续部分参见:
https://blog.csdn.net/Thomson617/article/details/83280617
Hive下的SQL语法总结:


   
   
  1. ( 1).Hive不支持 join的非等值连接,不支持 or
  2. 分别举例如下及实现解决办法。
  3. 不支持不等值连接
  4. 错误: select * from a inner join b on a.id <>b.id
  5. 替代方法: select * from a inner join b on a.id =b.id and a.id is null;
  6. 不支持 or
  7. 错误: select * from a inner join b on a.id =b.id or a.name =b.name
  8. 替代方法: select * from a inner join b on a.id =b.id
  9. union all
  10. select * from a inner join b on a.name =b.name
  11. 两个 sql union all的字段名必须一样或者列别名要一样。
  12. ( 2).分号字符:不能智能识别concat(‘;’,key),只会将‘;’当做 SQL结束符号。
  13. •分号是 SQL语句结束标记,在HiveQL中也是,但是在HiveQL中,对分号的识别没有那么智慧,例如:
  14. select concat(key,concat( ';',key)) from dual;
  15. •但HiveQL在解析语句时提示:
  16. FAILED: Parse Error: line 0: -1 mismatched input '<EOF>' expecting ) in function specification
  17. •解决的办法是,使用分号的八进制的ASCII码进行转义,那么上述语句应写成:
  18. select concat(key,concat( '\073',key)) from dual;
  19. ( 3).不支持 INSERT INTOValues(), UPDATE, DELETE等操作.这样的话,就不要很复杂的锁机制来读写数据。
  20. INSERT INTO syntax is only available starting in version 0.8INSERT INTO就是在表或分区中追加数据。
  21. ( 4).HiveQL中String类型的字段若是空( empty)字符串, 即长度为 0, 那么对它进行 IS NULL的判断结果是 False,使用 left join可以进行筛选行。
  22. ( 5).不支持 ‘ < dt <’这种格式的范围查找,可以用dt in(”,”)或者 between替代。
  23. ( 6).Hive不支持将数据插入现有的表或分区中,仅支持覆盖重写整个表,示例如下:
  24. INSERT OVERWRITE TABLE t1 SELECT * FROM t2;
  25. ( 7). group by的字段,必须是 select后面的字段, select后面的字段不能比 group by的字段多.
  26. 如果 select后面有聚合函数,则该 select语句中必须有 group by语句
  27. 而且 group by后面不能使用别名
  28. ( 8).hive的 0.13版之前 select , wherehaving 之后不能跟子查询语句(一般使用 left joinright join 或者 inner join替代)
  29. ( 9).先 join(及 inner join) 然后 left joinright join
  30. ( 10).hive不支持group_concat方法,可用 concat_ws( '|', collect_set(str)) 实现
  31. ( 11). not in<> 不起作用,可用 left join tmp on tableName.id = tmp.id where tmp.id is null 替代实现
  32. ... ...
  •  
1.上传tar包 2.解压 tar -zxvf hive-1.2.1.tar.gz 3.安装mysql数据库 推荐yum 在线安装 4.配置hive (a)配置HIVE_HOME环境变量 vi conf/hive-env.sh 配置其中的$hadoop_home (b)配置元数据库信息 vi hive-site.xml 添加如下内容: javax.jdo.option.ConnectionURL jdbc:mysql://localhost:3306/hive?createDatabaseIfNotExist=true JDBC connect string for a JDBC metastore javax.jdo.option.ConnectionDriverName com.mysql.jdbc.Driver Driver class name for a JDBC metastore javax.jdo.option.ConnectionUserName root username to use against metastore database javax.jdo.option.ConnectionPassword hadoop password to use against metastore database 5.安装hive和mysq完成后,将mysql的连接jar包拷贝到$HIVE_HOME/lib目录下 如果出现没有权限的问,在mysql授权(在安装mysql的机器上执行) mysql -uroot -p #(执行下面的语句 *.*:所有库下的所有表 %:任何IP地址或主机都可以连接) GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION; FLUSH PRIVILEGES; 6. Jline包版本不一致的问,需要拷贝hive的lib目录中jline.2.12.jar的jar包替换掉hadoop中的 /home/hadoop/app/hadoop-2.6.4/share/hadoop/yarn/lib/jline-0.9.94.jar 启动hive bin/hive ---------------------------------------------------------------------------------------------------- Hive几种使用方式: 1.Hive交互shell bin/hive 2.Hive JDBC服务(参考java jdbc连接mysql) 3.hive启动为一个服务器,来对外提供服务 bin/hiveserver2 nohup bin/hiveserver2 1>/var/log/hiveserver.log 2>/var/log/hiveserver.err & 启动成功后,可以在别的节点上用beeline去连接 bin/beeline -u jdbc:hive2://mini1:10000 -n root 或者 bin/beeline ! connect jdbc:hive2://mini1:10000 4.Hive命令 hive -e ‘sql’ bin/hive -e 'select * from t_test'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值