这篇文章中具体使用的是PL/SQL语法,之前一直放在Oracle分类中。但是考虑到如今SQL Server,MySQL都支持windows functions了(有时也叫analytic functions),所以把文章整理后放到了单独的分类中。

其实面试时对SQL的考察还是比较简单的,主要的考察点是:

1,基本的表join。主要考察inner join和left join。

2,group by的使用。

3,开窗函数(也称为分析函数)。这通常是高级一点的应用了,不一定会考察到。pivot函数等因为并不常用,基本都不会涉及。

总之对SQL的考察基本上还是立足于实际,考察面试人解决实际问题的能力。

基础部分:

------------------------------------------------------------------------------

下面的练习题是针对订单表(订单信息)和订单详表(存储一个订单对应的多个物品):

Order_id, Customer_id, order_date
O1, C1, 01-Jan-2000
O2, C2, 01-Jan-2002
O3, C3, 01-Apr-2002
O4, C4, 01-Apr-2003
O5, C4, 01-Jan-2006
O6,C1, 01-May-2006
Item_id, Order_id
I1, O1
I2, O1
I3, O1
I1, O2
I5, O3

准备数据。注意对于标准SQL而言,是不能批量运行多条语句的,且结尾不能有;。因此想批量执行下面的插入SQL,则需要使用PL/SQL的语法,即使用block,且SQL结尾可以使用;。

或者使用http://sqlfiddle.com/ ,一个非常方便的online联系SQL的网站。直接将多行insert语句copy进去就可以执行。

begin
CREATE TABLE ORDER_LIST (ORDER_ID CHAR(2), CUSTOMER_ID CHAR(2), ORDER_DATE DATE);
INSERT INTO ORDER_LIST VALUES ('O1','C1',TO_DATE('2000-01-01','YYYY-MM-DD'));
INSERT INTO ORDER_LIST VALUES ('O2','C2',TO_DATE('2002-01-01','YYYY-MM-DD'));
INSERT INTO ORDER_LIST VALUES ('O3','C3',TO_DATE('2002-04-01','YYYY-MM-DD'));
INSERT INTO ORDER_LIST VALUES ('O4','C4',TO_DATE('2003-04-01','YYYY-MM-DD'));
INSERT INTO ORDER_LIST VALUES ('O5','C4',TO_DATE('2006-01-01','YYYY-MM-DD'));
INSERT INTO ORDER_LIST VALUES ('O6','C1',TO_DATE('2006-04-01','YYYY-MM-DD'));
CREATE TABLE ORDER_ITEMS (ITEM_ID CHAR(2), ORDER_ID CHAR(2));
INSERT INTO ORDER_ITEMS VALUES ('I1','O1');
INSERT INTO ORDER_ITEMS VALUES ('I2','O1');
INSERT INTO ORDER_ITEMS VALUES ('I3','O1');
INSERT INTO ORDER_ITEMS VALUES ('I1','O2');
INSERT INTO ORDER_ITEMS VALUES ('I5','O2');
INSERT INTO ORDER_ITEMS VALUES ('I1','O3');
INSERT INTO ORDER_ITEMS VALUES ('I4','O1');
INSERT INTO ORDER_ITEMS VALUES ('I1','O4');
end

Given order and order items tables, select customer ids of customers who placed orders with more than 3 items (having or subquery)

SELECT A.CUSTOMER_ID, COUNT(B.ITEM_ID)
FROM ORDER_LIST A, ORDER_ITEMS B
WHERE A.ORDER_ID = B.ORDER_ID
GROUP BY A.CUSTOMER_ID
HAVING COUNT(B.ITEM_ID) > 3;

Give SQL for the list of customer_ids who placed more than 1 order

SELECT CUSTOMER_ID, COUNT(order_id)
FROM ORDER_LIST lists
GROUP BY CUSTOMER_ID
HAVING COUNT(order_id) > 1

Give the Sql for the list of customer_ids who have placed at least 1 order in 2000 and at least 1 order in 2006.

select customer_id
from order_list
where extract(year from order_date) = 2000
intersect -- 这里注意intersect不会返回重复值,相当于做了distinct。
select customer_id
from order_list
where extract(year from order_date) = 2006

Please write a sql which can generate the number of Orders for each year, 2000 to 2006. 这道题的难点是:对于那些没有订单的年份,依然要在结果中,且订单数为0.

SELECT A.YEAR,NVL(B.ORDER_NUMBER,0)
FROM (SELECT 2001 AS YEAR FROM DUAL
UNION -- 这里注意union不会返回重复值,相当于做了distinct。
SELECT 2002 AS YEAR  FROM DUAL
UNION
SELECT 2003 AS YEAR  FROM DUAL
UNION
SELECT 2004 AS YEAR  FROM DUAL
UNION
SELECT 2005 AS YEAR  FROM DUAL
UNION
SELECT 2006 FROM DUAL) A,
(SELECT TO_CHAR(ORDER_DATE,'YYYY') YEAR, COUNT(ORDER_ID) ORDER_NUMBER
FROM ORDER_LIST
GROUP BY TO_CHAR(ORDER_DATE,'YYYY')) B
WHERE A.YEAR = B.YEAR (+)
ORDER BY A.YEAR;

或:

SELECT DECODE(TRUNC(order_date,'YEAR'),TO_DATE('2000-01-01','YYYY-mm-DD'),'2000-01-01',TO_DATE('2001-01-01','YYYY-mm-DD'),'2001-01-01',TO_DATE('2002-01-01','YYYY-mm-DD'),'2002-01-01',TO_DATE('2003-01-01','YYYY-mm-DD'),'2003-01-01',TO_DATE('2004-01-01','YYYY-mm-DD'),'2004-01-01',TO_DATE('2005-01-01','YYYY-mm-DD'),'2005-01-01',TO_DATE('2006-01-01','YYYY-mm-DD'),'2006-01-01')new_date,count(order_id)
FROM order_list_luyan
group by DECODE(TRUNC(order_date,'YEAR'),TO_DATE('2000-01-01','YYYY-mm-DD'),'2000-01-01',TO_DATE('2001-01-01','YYYY-mm-DD'),'2001-01-01',TO_DATE('2002-01-01','YYYY-mm-DD'),'2002-01-01',TO_DATE('2003-01-01','YYYY-mm-DD'),'2003-01-01',TO_DATE('2004-01-01','YYYY-mm-DD'),'2004-01-01',TO_DATE('2005-01-01','YYYY-mm-DD'),'2005-01-01',TO_DATE('2006-01-01','YYYY-mm-DD'),'2006-01-01')
order by new_date

进阶部分:

---------------------------------------------------------------------------

下面的练习题是针对员工表:

emp_id dep_id manager_id start_date salary
-----------------------------------
1,1,null,2000-01-01,16000
2,1,1,2002-01-01,20000
3,1,1,2002-04-01,9000
4,1,1,2003-04-01,1000
5,2,null,2006-01-01,20000
6,2,5,2006-04-01,28000
7,2,5,2000-04-01,500

准备数据:

CREATE TABLE employee (emp_id NUMBER(5), dep_id NUMBER(5), manager_id NUMBER(5) ,start_date DATE, salary NUMBER(5));
INSERT INTO employee VALUES (1,1,null,TO_DATE('2000-01-01','YYYY-MM-DD'), 16000);
INSERT INTO employee VALUES (2,1,1,TO_DATE('2002-01-01','YYYY-MM-DD'), 20000);
INSERT INTO employee VALUES (3,1,1,TO_DATE('2002-04-01','YYYY-MM-DD'), 9000);
INSERT INTO employee VALUES (4,1,1,TO_DATE('2003-04-01','YYYY-MM-DD'), 1000);
INSERT INTO employee VALUES (5,2,null,TO_DATE('2006-01-01','YYYY-MM-DD'), 20000);
INSERT INTO employee VALUES (6,2,5,TO_DATE('2006-04-01','YYYY-MM-DD'), 28000);
INSERT INTO employee VALUES (7,2,5,TO_DATE('2000-04-01','YYYY-MM-DD'), 500);

Display the employee records who joins the department before their manager?

SELECT a.*
FROM employee a, employee b
WHERE a.manager_id = b.emp_id
AND a.dep_id = b.dep_id
AND a.start_date < b.start_date;

Display employee records getting more salary than the average salary in their department?

SELECT a.*
FROM employee a, (
SELECT dep_id, AVG(salary) avg_sal
FROM employee
GROUP BY dep_id) b
WHERE a.dep_id = b.dep_id
AND a.salary > b.avg_sal

或相关子查询的写法:

相关子查询的特点是,每当主查询或外查询执行一次时,会执行一次相关子查询。下面的相关子查询的运行顺序是:先获取主查询的一个dep_id,在子查询中统计对应的averge。注意由于子查询已经到部门内部了,所以子查询中不再需要写group by语句(写或不写效果一样)。

SELECT a.*
FROM employee a
WHERE salary > (SELECT AVG(salary) max_sal
FROM employee b
WHERE a.dep_id = b.dep_id);

Display the highest paid employee in each department.

SELECT a.*
FROM employee a, (
SELECT dep_id, MAX(salary) max_sal
FROM employee
GROUP BY dep_id) b
WHERE a.dep_id = b.dep_id
AND a.salary = b.max_sal

SELECT a.*
FROM employee a
WHERE salary = (
SELECT MAX(salary) max_sal
FROM employee b
WHERE a.dep_id = b.dep_id ); 

对rownum的使用:

SELECT *
FROM employee
where rownum < 4
order by dep_id desc

由上例结果可知,先用rownum选取了3行数据,再运行order by。order by永远是最后运行的语句。

SELECT *
FROM employee
where rownum between 1 and 5select rownum, emp_id
from employee

由上例结果可知,rownum = 1表示查一行数据,等于其他数字是不能查出数据的;rownum < 4 返回3行数据;rownum <=4 返回4行数据;rownum 在1到5之间返回5行数据;rownum = 5 是不能查出数据的;rownum > 1 或任何数字均不能查出数据,但rownum > 0返回表中所有数据。

rownum是动态的,先得到结果集,再加上序号,因此rownum >10不能得到结果,但rownum>0可以得到所有数据。因为先得到10行数据,然后对第一行编号1,因为1不满足>10,因此被过滤掉。第二行数据又编号为1,因此又被过滤。以此类推,结果就是返回空集。rownum = 5 不能查出数据但是=1可以,因为先得到第5行,然后编号为1,然后又被=5过滤掉。

使用rownum查询工资从最高开始的top 3:

select rownum, a.*
from (
select *
from employee
order by salary desc) a
where rownum between 1 and 3

因此想得到top 3 数据,需要首先对子查询排序,然后用rownum。注意以下写法是错误的:

select a.*
from (
select rownum rownumber, emp_id, salary
from employee_1
order by salary desc) a
where a.rownumber between 1 and 3

原因是子查询里的order by也总是最后一个执行,因此子查询的运行顺序是先rownum,后order by,因此返回的rownum不是按工资排倒序的。

将上题改为返回每个部门的salary top 3员工,则需要使用分析函数:

select *
from (
select dep_id, emp_id,row_number() over (partition by dep_id order by salary desc) top_in_dep
from employee_luyan)
where top_in_dep <= 3

SQL面试练习题一(基础)相关推荐

  1. SQL Server 练习题(初学)

    SQL Server 练习题(基础) 一.前言 二.准备 三.练习 1.创建练习题目的数据库(新建查询) 2.练习题 一.前言 新学了一门<数据库原理及应用>,布置了一些基础题目,互相学习 ...

  2. 拿捏SQL数据分析:从基础破冰到面试题解

    目前,在各大招聘网站查询数据分析相关岗位时,在任职要求一栏中基本都会看到"熟练运用 SQL"的要求,SQL 可以说是数据分析相关岗位的必备基础技能. 数据分析对 SQL 有哪些基本 ...

  3. sql基础教程亚马逊_针对Amazon,Apple,Google的常见SQL面试问题

    sql基础教程亚马逊 SQL is used in a wide variety of programming jobs. It's important to be familiar with SQL ...

  4. hive sql练习_经典的SparkSQL/Hive-SQL/MySQL面试-练习题

    经典的SparkSQL/Hive-SQL/MySQL面试-练习题​mp.weixin.qq.com 第一题 需求: 已知一个表order,有如下字段:date_time,order_id,user_i ...

  5. linux+sql面试常见基础八股文

    linux篇 conda env list 查看镜像 source deactivate 关闭虚拟环境 source activate wfy 激活 虚拟环境 conda create -n your ...

  6. mysql测试题汇总_总结:SQL练习【SQL经典练习题】

    好像今天圣诞节 刚刷完SQL练习[SQL经典练习题],本篇文章将对我不牢固的知识做简单汇总. 没对比就没标准,当练习超经典SQL练习题,做完这些你的SQL就过关了时才知道自己以前练习的SQL是最基础的 ...

  7. sql学习练习题_学习SQL:练习SQL查询

    sql学习练习题 Today is the day for SQL practice #1. In this series, so far, we've covered most important ...

  8. 关系数据库SQL面试排名前100道问答题

    RDBMS 是迄今为止最常用的数据库之一,因此SQL 技能在大多数工作角色中必不可少.在这篇 SQL 面试问题文章中,我将向您介绍有关 SQL(结构化查询语言)的最常见问题.本文是您学习与 SQL.O ...

  9. 33个必须知道的数据分析师SQL面试问题和答案

    33个必须知道的数据分析师SQL面试问题和答案 SQL是一种强大的编程语言,被广泛用于管理和分析数据.如果你想成为一名数据分析师,或者是正在寻找新工作的现有分析师,准备好回答SQL面试问题是很重要的. ...

最新文章

  1. webp app推荐图片格式,更小更快减少oom
  2. tomcat启动报错APR问题
  3. matplotlib 散点图_python之matplotlib 折线图和散点图
  4. Xamarin For Visual Studio 3.7.165 完整离线破解版
  5. 自动驾驶 4-4 纵向车辆建模Longitudinal Vehicle Modeling
  6. 活着只是你幸运--512汶川大地震募捐倡议
  7. Java代码执行Linux脚本
  8. springboot毕设项目银行助学贷款管理系统0o571(java+VUE+Mybatis+Maven+Mysql)
  9. 分析图书管理系统的5W1H
  10. VMware ESXI7.0的安装与配置(全过程超详细含中英文对照,附应知必会的理论基础和常见故障解决方案)
  11. uniapp+微信小程序云函数获取微信openId
  12. 解读 | 关于阿里巴巴架构大调整,有 7 个重点值得特别关注
  13. HDL4SE:软件工程师学习Verilog语言(十三)
  14. 苹果mac启动台变成问号_MAC开机停止响应并出现闪烁问号的解决方法
  15. GMark 0.8.6 无法显示Google Bookmarks
  16. 设计模式|代理模式、以《安家》为模型轻松理解静态代理和动态代理
  17. CPU的功能和基本结构
  18. 卷积神经网络超详细介绍(转载)
  19. python画条形图并分类-python matplotlib库绘制条形图练习题
  20. 历经艰难,终成大器!改变,永远不迟!

热门文章

  1. 第四章 智能合约 [20]
  2. C#大恒相机采集图片时图片上下对称折叠了
  3. vm装linux不能上网 系统,VM 安装Linux后,以前的系统无法上网
  4. MySQL DBA 必读:万字归总表设计与 SQL 编写技巧
  5. 微信小程序开发百度云分享
  6. CentOS.7卸载与安装Nvidia Driver
  7. 高校最低分数录取线c语言,全国: 2018年普通高等学校招生录取最低控制分数线...
  8. 学生信息管理系统——错误集锦(五)
  9. 提高计算机主频的方法,cpu主频如何调高
  10. Pytorch实现Bert模型