hiveSQL面试60题

http://hi.baidu.com/eva%B0%D9%B7%D6%B0%D9/blog/item/1dd7b5d3e5ea419fa1ec9c8a.html
员工部门表综合查询60题(上)
2010-11-24 06:04员工部门表综合查询60题(上)

CREATE DATABASE oa;
USE oa;

CREATE TABLE dept(
deptno INT PRIMARY KEY,
dname VARCHAR(20),
loc VARCHAR(20)
)

DROP TABLE emp
CREATE TABLE emp(
empno INT PRIMARY KEY,
ename VARCHAR(20) NOT NULL,
job VARCHAR(20) CHECK (job IN (‘CLERK’,‘SALESMAN’,‘MANAGER’,‘SALESMAN’,‘ANALYST’)),
mgp INT ,
hiredate DATETIME ,
sal DECIMAL(10,2),
comm DECIMAL(10,2),
DEPTNO INT FOREIGN KEY REFERENCES dept(deptno)
)

INSERT INTO dept VALUES (10,‘ACCOUNTING’,‘NEWTORK’)
INSERT INTO dept VALUES (20,‘RESEARCH’,‘DALLAS’)
INSERT INTO dept VALUES (30,‘SALES’,‘CHICAGO’)
INSERT INTO dept VALUES (40,‘OPERATIONS’,‘BOSTON’)

insert into emp values(7369,‘SMITH’,‘CLERK’,7902,‘1980-12-17’,1640,NULL,20);
insert into emp values(7499,‘ALLEN’,‘SALESMAN’,7698,‘1981-2-20’,11400,300,30);
insert into emp values(7521,‘WARD’,‘SALESMAN’,7698,‘1981-2-22’,5200,500,30);
insert into emp values(7566,‘JOENS’,‘MANAGER’,7839,‘1981-4-2’,7015,NULL,20);
insert into emp values(7654,‘MARTIN’,‘SALESMAN’,7698,‘1981-9-28’,5200,1400,30);
insert into emp values(7698,‘BLAKE’,‘MANAGER’,7839,‘1981-5-1’,5900,NULL,30);
insert into emp values(7782,‘CLARK’,‘MANAGER’,7839,‘1981-6-9’,2470,NULL,10);
insert into emp values(7788,‘SCOTT’,‘ANALYST’,7566,‘1987-4-19’,3040,NULL,20);
insert into emp values(7844,‘TURNER’,‘SALESMAN’,7698,‘1980-12-17’,6200,0,30);
insert into emp values(7876,‘ADAMS’,‘CLERK’,7788,‘1981-9-8’,2240,NULL,20);
insert into emp values(7900,‘JAMES’,‘CLERK’,7698,‘1987-5-23’,4000,NULL,30);
insert into emp values(7902,‘FORD’,‘ANALYST’,7566,‘1981-12-3’,3040,NULL,20);
insert into emp values(7934,‘MILLER’,‘CLERK’,7782,‘1982-12-3’,2620,NULL,10);

SELECT * FROM emp;
select * from dept;

员工部门表综合查询60题

(1) 查询20部门的所有员工信息。
select * from emp where deptno=20;

(2) 查询所有工种为CLERK的员工的员工号、员工名和部门号。
select empno,ename,deptno from emp where job=‘CLERK’

(3) 查询奖金(COMM)高于工资(SAL)的员工信息。
select * from emp where isnull(comm,0)>sal

(4) 查询奖金高于工资的20%的员工信息。
select * from emp where isnull(comm,0)>sal*0.2

(5) 查询10号部门中工种为MANAGER和20部门中工种为CLERK的员工的信息。
select * from emp
where job=‘MANAGER’ and deptno=10
union
select * from emp
where job=‘CLERK’ and deptno=20


select * from emp
where (job=‘MANAGER’ and deptno=10)
or (job=‘CLERK’ and deptno=20
)

(6) 查询所有工种不是MANAGER和CLERK,
–且工资大于或等于2000的员工的详细信息。
select * from emp
where job not in(‘MANAGER’,‘CLERK’)
and sal>=2000

(7) 查询有奖金的员工的不同工种。
select distinct job from emp
where comm is not null

(8) 查询所有员工工资与奖金的和。
select ename,sal+isnull(comm,0) 实发工资
from emp

(9) 查询没有奖金或奖金低于100的员工信息。
select *
from emp
where comm is null or comm<100

(10) 查询各月倒数第3天(倒数第2天)入职的员工信息。
select *
from emp
where DATENAME(day,hiredate+3)=1

(11) 查询工龄大于或等于25年的员工信息。
select ename 姓名,hiredate 雇用日期,datediff(year,hiredate,getdate()) 工资
from emp
where datediff(year,hiredate,getdate())>=25

(12) 查询员工信息,要求以首字母大写的方式显示所有员工的姓名。
select upper(SUBSTRING(ename,1,1))+lower(substring(ename,2,(len(ename)-1)))
from emp

(13) 查询员工名正好为6个字符的员工的信息。
select ename from emp where len(ename)=6

(14) 查询员工名字中不包含字母“S”的员工。
select ename from emp where ename not like ‘%S%’

(15) 查询员工姓名的第二字母为“M”的员工信息。
select ename from emp
where ename like ‘_M%’

(16) 查询所有员工姓名的前三个字符。
select ename 员工姓名,substring(ename,1,3) 员工姓名的前三个字符
from emp

(17) 查询所有员工的姓名,如果包含字母“S”,则用“s”替换。
–返回被替换了指定子串的字符串。
–REPLACE (<string_expression1>,<string_expression2>,<string_expression3>)
–用string_expression3 替换在string_expression1 中的子串string_expression2。
select replace(ename,‘S’,‘s’)
from emp

(18) 查询员工的姓名和入职日期,并按入职日期从先到后进行排序。
select ename,hiredate
from emp
order by hiredate

(19) 显示所有员工的姓名、工种、工资和奖金,按工种降序排序,
–若工种相同则按工资升序排序。
select ename,job,sal,comm
from emp
order by job desc

(20) 显示所有员工的姓名、入职的年份和月份,
–按入职日期所在的月份排序,若月份相同则按入职的年份排序。
select ename,hiredate 入职日期,DATENAME(yy,hiredate) 入职的年份,datename(mm,hiredate) 入职的月份
from emp

(21) 查询在2月份入职的所有员工信息。
select * from emp
where datename(mm,hiredate)=2

(4) 查询奖金高于工资的20%的员工信息。
select * from emp where isnull(comm,0)>sal*0.2

(22) 查询所有员工入职以来的工作期限,用“XX年XX月XX日”的形式表示。
select ename,
datename(yy,hiredate)+‘年’+datename(mm,hiredate)+‘月’+datename(dd,hiredate)+‘日’ 工作期限
from emp

(23.1) 查询至少有一个员工的部门信息。
select d.dname,count(empno) 部门人数
from emp e
right join dept d
on d.deptno=e.deptno
group by d.dname,e.deptno
having count(empno)>=1

(23.2) 查询至少有两个员工的部门信息。
select d.dname,count(empno) 部门人数
from emp e
right join dept d on d.deptno=e.deptno
group by d.dname,e.deptno
having count(empno)>1

(24) 查询工资比SMITH员工工资高的所有员工信息。
select *
from emp
where sal>(
select sal from emp where ename=‘SMITH’
)

(25) 查询所有员工的姓名及其直接上级的姓名。
select ename 员工的姓名,(
select ename from emp e2 where e2.empno=e1.mgp
) 直接上级
from emp e1

(26) 查询入职日期早于其直接上级领导的所有员工信息。
select ename 员工的姓名,hiredate 入职日期,(
select ename from emp e2 where e2.empno=e1.mgp
) 直接上级,(
select hiredate from emp e2 where e2.empno=e1.mgp
) 直接上级入职日期
from emp e1
where e1.hiredate<(select hiredate
from emp e2 where e2.empno=e1.mgp
)

(27) 查询所有部门及其员工信息,包括那些没有员工的部门。
select dept.dname,emp.ename
from dept
left outer join emp on emp.deptno=dept.deptno

(28) 查询所有员工及其部门信息,包括那些还不属于任何部门的员工。
select dept.dname,emp.ename
from emp
left outer join dept on emp.deptno=dept.deptno

(29) 查询所有工种为CLERK的员工的姓名及其部门名称。
select dept.dname,emp.ename,emp.job
from emp
left outer join dept on emp.deptno=dept.deptno
where job=‘CLERK’

(30) 查询最低工资大于2500的各种工作。
select job,sal
from emp
where sal>2500


员工部门表综合查询60题(下)
2010-11-26 11:31员工部门表综合查询60题(下)

(31) 查询平均工资低于2000的部门及其员工信息。
select *
from dept left outer join emp on dept.deptno=emp.deptno
where dept.deptno in (
select deptno from emp
group by deptno
having avg(sal)<2000)

(32) 查询在SALES部门工作的员工的姓名信息。
–法一:表连接
select *
from dept left outer join emp on dept.deptno=emp.deptno
where dept.dname=‘SALES’

–法二:子查询
select * from emp
where emp.deptno=(
select deptno from dept where dname=‘SALES’
)

(33) 查询工资高于公司平均工资的所有员工信息。
select * from emp
where sal>(
select avg(sal)
from emp)

(34) 查询出与SMITH员工从事相同工作的所有员工信息。
select * from emp where job = (
select job
from emp
where ename=‘SMITH’)

(35) 列出工资等于30部门中某个员工的工资的所有员工的姓名和工资。
select *
from emp
where sal in (
select sal
from emp
where deptno=30) and deptno!=30

(36) 查询工资高于30部门工作的所有员工的工资的员工姓名和工资。

select *
from emp
where sal > all(
select sal
from emp
where deptno=30)

(37) 查询每个部门中的员工数量、平均工资和平均工作年限。
select dname 部门,count(ename) 员工数量,isnull(avg(sal),0) 平均工资,
isnull(avg(datediff(yy,hiredate,getdate())),0) 平均工作年限
from dept d
left outer join emp e on d.deptno=e.deptno
group by d.dname

(38) 查询从事同一种工作但不属于同一部门的员工信息。
select *
from emp e1
where e1.job in (
select distinct e2.job
from emp e2
where e2.deptno != e1.deptno
)

(39) 查询各个部门的详细信息以及部门人数、部门平均工资。
select d.dname 部门名称,d.deptno 部门编号,count(e.empno) 人数,avg(e.sal) 平均工资
from dept d
left outer join emp e on d.deptno=e.deptno
group by d.deptno,d.dname

(40) 查询各种工作的最低工资。
select job 工种,min(sal) 最低工资
from emp
group by job

(41) 查询各个部门中不同工种的最高工资。
select dname 部门名称,job 工种,max(isnull(sal,0)) 最高工资
from dept d left join emp e on d.deptno=e.deptno
group by job,dname

(42) 查询10号部门员工及其领导的信息。
select deptno 部门,ename 姓名 ,(select e2.ename from emp e2 where e2.mgp=e1.empno) 上级领导
from emp e1
where deptno=10

(43) 查询各个部门的人数及平均工资。
select dname 部门名称,count(ename) 部门人数,avg(isnull(sal,0)) 平均工资
from dept d left outer join emp e on d.deptno=e.deptno
group by d.dname

(44) 查询工资为某个部门平均工资的员工的信息。
select * from emp
where sal in(
select avg(sal)
from emp group by deptno
)

(45) 查询工资高于本部门平均工资的员工的信息。
select *
from emp e1
where sal>(
select avg(sal)
from emp e2
where e2.deptno=e1.deptno
)

(46) 查询工资高于本部门平均工资的员工的信息及其部门的平均工资。
select *,(select avg(sal) from emp e2 where e2.deptno=e1.deptno) 部门平均工资
from emp e1
where sal>(
select avg(sal) from emp e2 where e2.deptno=e1.deptno
)

(47) 查询工资高于20号部门某个员工工资的员工的信息。
select *
from emp e1
where sal> any(
select sal from emp e where deptno=20
)

(48)统计各个工种的员工人数与平均工资。
select job 工种,count(empno) 员工人数,avg(sal) 平均工资
from emp
group by job

(49) 统计每个部门中各工种的人数与平均工资。
select dname 部门,job 工种,count(empno) 人数,avg(isnull(sal,0)) 平均工资
from dept d left outer join emp e on d.deptno=e.deptno
group by job,dname

(50) 查询其他部门中工资、奖金与30号部门某员工工资、
–奖金都相同的员工的信息。没有查询结果
select *
from emp e
where isnull(sal,0)+isnull(comm,0) in (
select isnull(sal,0)+isnull(comm,0)
from emp e1
where e1.deptno=30 and e.sal=e1.sal and e.comm=e1.comm and e.deptno!=30
)

(51) 查询部门人数大于5的部门的员工信息。
select * from emp
where deptno in(
select deptno
from emp
group by deptno
having count(empno)>5)

(52) 查询所有员工工资都大于1000的部门的信息。
select *
from dept d
where deptno in (
select deptno from emp e
group by deptno
having min(sal)>1000
)

(53) 查询所有员工工资都大于1000的部门的信息及其员工信息。
select *
from dept d left outer join emp e on d.deptno=e.deptno
where e.deptno in (
select deptno from emp e1
group by deptno
having min(sal)>1000
)

(54) 查询所有员工工资都在900~3000之间的部门的信息。
select * from dept
where deptno in(
select deptno from emp
group by deptno
having min(sal)>900 and max(sal)<3000
)

(55) 查询有工资在900~3000之间的员工所在部门的员工信息。
select * from emp
where deptno in(
select deptno from emp
group by deptno
having min(sal)>900 and max(sal)<3000
)

(56) 查询每个员工的领导所在部门的信息。
select ename 员工,(
select e1.ename from emp e1 where emp.mgp=e1.empno
) 领导,(
select d.dname
from emp e left outer join dept d on e.deptno=d.deptno
where emp.mgp=e.empno
) 领导所在部门
from emp

(57) 查询人数最多的部门信息。
select * from dept
where deptno =(
select top 1 deptno
from emp
group by deptno
order by -count(empno))

(58) 查询30号部门中工资排序前3名的员工信息。
select top 3 *
from emp
where deptno=30
order by -sal

(59) 查询所有员工中工资排序在5到10名之间的员工信息。
select top 5 *
from (
select top 10 *
from emp
order by -sal) e
order by sal

(60) 查询指定年份之间入职的员工信息。(1980-1985)
select *
from emp
where datename(year,hiredate) between 1980 and 1985

<think>嗯,用户想找Hive SQL相关的面试和答案。首先,我需要回忆一下常见的Hive面试,比如窗口函数、数据转换、去重等等。根据提供的引用内容,看到有同时在线人数、行转列、列转行等问。比如引用[1]中的同时在线人数计算,用到了UNION ALL和窗口函数sum() over(),这个应该是经典问之一。还有引用[3]中的collect_list函数用来拼接字符串,这也是常见的行转列问。引用[4]提到的split和explode则是列转行的例子。 接下来需要整理这些问,并给出对应的答案和示例代码。用户可能需要分点回答,结构清晰。比如第一个问同时在线人数,需要步骤分解,说明如何将登录登出时间合并,然后用窗口函数累加。第二个问行转列,用collect_list或者concat_ws。第三个问列转行,用lateral view explode。第四个数据去重,可以用row_number或者group by。第五个连续登录,用日期差和分组统计。 还要注意用户的系统级指令,比如数学公式用$...$,代码块正确使用格式,引用标记在末尾。比如在回答每个问时,适当引用提供的参考资料,如[^1]、[^3]、[^4]等。同时生成相关问,可能包括性能优化、其他函数应用、处理数据倾斜等。 需要确保每个问都有对应的SQL示例,并且代码正确。比如在同时在线人数的问中,UNION ALL合并登录登出记录,然后sum(tag) over计算实时人数。在行转列中,collect_list和concat_ws的使用。列转行中的split和explode组合。 还要注意用户提到的“生成相关问”部分,需要列出几个相关的问,比如优化方法、其他窗口函数应用、数据倾斜处理等,这样用户可以有进一步的学习方向。 最后,检查是否所有引用都正确标注,答案是否符合中文要求,结构是否清晰,有没有遗漏常见的Hive面试。可能需要补充一些其他常见问,比如分区和分桶的区别、Hive和传统数据库的区别等,但根据提供的引用内容,主要围绕已有例子展开。</think>### Hive SQL 常见面试及答案 #### 1. **如何计算某时段内同时在线的最多人数?** **答案**: 将登录时间标记为$+1$,登出时间标记为$-1$,合并后通过窗口函数累加计算实时人数。示例代码: ```sql WITH t1 AS ( SELECT login_ts ts, 1 AS tag FROM user_login_detail UNION ALL SELECT logout_ts ts, -1 AS tag FROM user_login_detail ) SELECT MAX(cn) AS max_online_count FROM ( SELECT SUM(tag) OVER (ORDER BY ts) AS cn FROM t1 ) t2; ``` **解析**: - 使用`UNION ALL`合并登录和登出动作的时间戳。 - 窗口函数`SUM(tag) OVER (ORDER BY ts)`按时间顺序累加人数,最终取最大值。 --- #### 2. **如何将多行数据合并为一行(行转列)?** **答案**: 使用`COLLECT_LIST()`或`COLLECT_SET()`聚合函数,结合`CONCAT_WS()`拼接字符串。示例: ```sql SELECT user_id, CONCAT_WS(',', COLLECT_LIST(product_id)) AS purchased_products FROM purchase_table GROUP BY user_id; ``` **解析**: - `COLLECT_LIST`收集所有商品ID(允许重复),`COLLECT_SET`去重。 - `CONCAT_WS`用逗号分隔拼接结果。 --- #### 3. **如何将一行数据拆分为多行(列转行)?** **答案**: 使用`LATERAL VIEW`与`EXPLODE()`函数展开数组。示例: ```sql SELECT name, subject_name FROM student_table LATERAL VIEW EXPLODE(SPLIT(subject_list, ',')) extend_sub AS subject_name; ``` **解析**: - `SPLIT(subject_list, ',')`将字符串转换为数组。 - `EXPLODE()`展开数组,`LATERAL VIEW`生成多行结果。 --- #### 4. **如何对重复数据进行去重?** **答案**: 使用`ROW_NUMBER()`窗口函数标记重复项,或直接使用`GROUP BY`。示例: ```sql -- 方法1:窗口函数 SELECT * FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY login_ts DESC) AS rn FROM login_table ) t WHERE rn = 1; -- 方法2:GROUP BY SELECT user_id, MAX(login_ts) AS last_login FROM login_table GROUP BY user_id; ``` --- #### 5. **如何统计用户连续登录天数?** **答案**: 通过日期差与分组标记实现。示例: ```sql WITH t1 AS ( SELECT user_id, login_date, DATE_SUB(login_date, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY login_date)) AS grp FROM login_table ) SELECT user_id, COUNT(*) AS consecutive_days FROM t1 GROUP BY user_id, grp HAVING COUNT(*) >= 3; -- 连续3天以上 ``` **解析**: - `DATE_SUB(login_date, ROW_NUMBER())`生成连续登录的分组标记[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值