哈Ha!
三年多来,我一直在各种培训中心教授SQL,并且我的观察之一是,如果学生设定任务,就会更好地掌握和理解SQL,而不仅仅是谈论各种可能性和理论基础。
在本文中,我将与您分享我作为作业做的任务清单,并在此清单上进行各种头脑风暴,从而使人们对SQL有了更深刻而清晰的理解。

SQL(英文结构化查询语言)是一种声明性编程语言,用于在由适当的数据库管理系统管理的关系数据库中创建,修改和管理数据。
了解更多您可以从各种
来源阅读有关SQL的信息。
本文的目的不是从头开始教您SQL。
所以走吧
我们将在Oracle及其表中使用著名的
HR模式 (
更多 ):

我注意到,我们将仅考虑SELECT任务。 DML和DDL没有问题。
任务
限制和排序数据员工表。 获取有关所有员工信息的列表
员工表。 获取名为“ David”的所有员工的列表
解决方案 SELECT * FROM employees WHERE first_name = 'David';
员工表。 获取job_id等于“ IT_PROG”的所有员工的列表
解决方案 SELECT * FROM employees WHERE job_id = 'IT_PROG'
员工表。 获取第50个部门(department_id)的所有雇员的清单,工资(薪金)超过4000
解决方案 SELECT * FROM employees WHERE department_id = 50 AND salary > 4000;
员工表。 获取第20部门和第30部门的所有员工的列表(department_id)
解决方案 SELECT * FROM employees WHERE department_id = 20 OR department_id = 30;
员工表。 获取名称中最后一个字母为“ a”的所有员工的列表
解决方案 SELECT * FROM employees WHERE first_name LIKE '%a';
员工表。 获取第50部门和第80部门(department_id)中有奖金的所有雇员的列表(Commission_pct列中的值不为空)
解决方案 SELECT * FROM employees WHERE (department_id = 50 OR department_id = 80) AND commission_pct IS NOT NULL;
员工表。 获取名称至少包含两个字母“ n”的所有员工的列表
解决方案 SELECT * FROM employees WHERE first_name LIKE '%n%n%';
员工表。 获取姓名超过4个字母的所有员工的列表
解决方案 SELECT * FROM employees WHERE first_name LIKE '%_____%';
员工表。 获取所有工资在8000到9000(含)范围内的雇员的列表
解决方案 SELECT * FROM employees WHERE salary BETWEEN 8000 AND 9000;
员工表。 获取名称包含字符“%”的所有雇员的列表
解决方案 SELECT * FROM employees WHERE first_name LIKE '%\%%' ESCAPE '\';
员工表。 获取所有ID管理器的列表
解决方案 SELECT DISTINCT manager_id FROM employees WHERE manager_id IS NOT NULL;
员工表。 获取以下格式的雇员列表:Donald(sh_clerk)
解决方案 SELECT first_name || '(' || LOWER (job_id) || ')' employee FROM employees;
使用单行功能自定义输出员工表。 获取姓名超过10个字母的所有员工的列表
解决方案 SELECT * FROM employees WHERE LENGTH (first_name) > 10;
员工表。 获取名称中带有字母“ b”的所有员工的列表(不区分大小写)
解决方案 SELECT * FROM employees WHERE INSTR (LOWER (first_name), 'b') > 0;
员工表。 获取名称至少包含两个字母“ a”的所有员工的列表
解决方案 SELECT * FROM employees WHERE INSTR (LOWER (first_name),'a',1,2) > 0;
员工表。 获取所有薪水为1000的倍数的员工的列表
解决方案 SELECT * FROM employees WHERE MOD (salary, 1000) = 0;
员工表。 如果员工的电话号码格式为XXXX.XXX.XXXX,请获取其前三位数字
解决方案 SELECT phone_number, SUBSTR (phone_number, 1, 3) new_phone_number FROM employees WHERE phone_number LIKE '___.___.____';
部门表。 对于名称中包含多个单词的人员,请从部门名称中获取第一个单词
解决方案 SELECT department_name, SUBSTR (department_name, 1, INSTR (department_name, ' ')-1) first_word FROM departments WHERE INSTR (department_name, ' ') > 0;
员工表。 获取员工姓名,姓名中不包括首字母和尾字母
解决方案 SELECT first_name, SUBSTR (first_name, 2, LENGTH (first_name) - 2) new_name FROM employees;
员工表。 获取所有姓氏中最后一个字母为'm'并且长名大于5的所有员工的列表
解决方案 SELECT * FROM employees WHERE SUBSTR (first_name, -1) = 'm' AND LENGTH(first_name)>5;
双表。 获取下一个星期五日期
解决方案 SELECT NEXT_DAY (SYSDATE, 'FRIDAY') next_friday FROM DUAL;
员工表。 获取在公司工作超过17年的所有员工的名单
解决方案 SELECT * FROM employees WHERE MONTHS_BETWEEN (SYSDATE, hire_date) / 12 > 17;
员工表。 获取所有员工的列表,这些员工的电话号码的最后一位数字为奇数,由3个数字组成,并用点号分隔
解决方案 SELECT * FROM employees WHERE MOD (SUBSTR (phone_number, -1), 2) != 0 AND INSTR (phone_number,'.',1,3) = 0 AND INSTR (phone_number,'.',1,2) > 0;
员工表。 获取所有在'_'符号后的job_id值中至少包含3个字符的员工的列表,但是'_'之后的值不等于'CLERK'
解决方案 SELECT * FROM employees WHERE LENGTH (SUBSTR (job_id, INSTR (job_id, '_') + 1)) > 3 AND SUBSTR (job_id, INSTR (job_id, '_') + 1) != 'CLERK';
员工表。 通过替换值PHONE_NUMBER中的所有“。”来获取所有员工的列表。 在“-”上
解决方案 SELECT phone_number, REPLACE (phone_number, '.', '-') new_phone_number FROM employees;
使用转换函数和条件表达式员工表。 获取每月第一天上班的所有员工的清单(任意)
解决方案 SELECT * FROM employees WHERE TO_CHAR (hire_date, 'DD') = '01';
员工表。 获取2008年上班的所有员工的名单
解决方案 SELECT * FROM employees WHERE TO_CHAR (hire_date, 'YYYY') = '2008';
双表。 以以下格式显示明天的日期:明天是一月的第二天
解决方案 SELECT TO_CHAR (SYSDATE, 'fm""Tomorrow is ""Ddspth ""day of"" Month') info FROM DUAL;
员工表。 以2007年6月21日的格式获取所有员工的名单以及每个人上班的日期。
解决方案 SELECT first_name, TO_CHAR (hire_date, 'fmddth ""of"" Month, YYYY') hire_date FROM employees;
员工表。 获取薪水增加20%的员工列表。 用美元符号显示薪水
解决方案 SELECT first_name, TO_CHAR (salary + salary * 0.20, 'fm$999,999.00') new_salary FROM employees;
员工表。 获取2007年2月上班的所有员工的名单。
解决方案 SELECT * FROM employees WHERE hire_date BETWEEN TO_DATE ('01.02.2007', 'DD.MM.YYYY') AND LAST_DAY (TO_DATE ('01.02.2007', 'DD.MM.YYYY')); SELECT * FROM employees WHERE to_char(hire_date,'MM.YYYY') = '02.2007';
双表。 取出当前日期,+秒,+分钟,+小时,+天,+月,+年
解决方案 SELECT SYSDATE now, SYSDATE + 1 / (24 * 60 * 60) plus_second, SYSDATE + 1 / (24 * 60) plus_minute, SYSDATE + 1 / 24 plus_hour, SYSDATE + 1 plus_day, ADD_MONTHS (SYSDATE, 1) plus_month, ADD_MONTHS (SYSDATE, 12) plus_year FROM DUAL;
员工表。 获取格式为:$ 24,000.00的所有具有完整薪水(薪金+ Commission_pct(%))的所有员工的列表。
解决方案 SELECT first_name, salary, TO_CHAR (salary + salary * NVL (commission_pct, 0), 'fm$99,999.00') full_salary FROM employees;
员工表。 获取所有员工的列表以及有关薪水奖金可用性的信息(是/否)
解决方案 SELECT first_name, commission_pct, NVL2 (commission_pct, 'Yes', 'No') has_bonus FROM employees;
员工表。 获取每个员工的薪水水平:低于5000视为低水平,大于或等于5000且小于10000被视为正常水平,大于或等于10000被视为高水平
解决方案 SELECT first_name, salary, CASE WHEN salary < 5000 THEN 'Low' WHEN salary >= 5000 AND salary < 10000 THEN 'Normal' WHEN salary >= 10000 THEN 'High' ELSE 'Unknown' END salary_level FROM employees;
国家表。 为每个国家/地区显示其所在的地区:1-欧洲,2-美国,3-亚洲,4-非洲(不加入)
解决方案 SELECT country_name country, DECODE (region_id, 1, 'Europe', 2, 'America', 3, 'Asia', 4, 'Africa', 'Unknown') region FROM countries; SELECT country_name country, CASE region_id WHEN 1 THEN 'Europe' WHEN 2 THEN 'America' WHEN 3 THEN 'Asia' WHEN 4 THEN 'Africa' ELSE 'Unknown' END region FROM countries;
使用组功能报告汇总数据员工表。 获取有关Department_id的报告,该报告具有最低和最高薪水,上班的早晚日期以及雇员人数。 按员工人数排序(降序)
解决方案 SELECT department_id, MIN (salary) min_salary, MAX (salary) max_salary, MIN (hire_date) min_hire_date, MAX (hire_date) max_hire_Date, COUNT (*) count FROM employees GROUP BY department_id order by count(*) desc;
员工表。 多少名以相同字母开头的员工? 按数量排序。 仅显示数量大于1的地方
解决方案 SELECT SUBSTR (first_name, 1, 1) first_char, COUNT (*) FROM employees GROUP BY SUBSTR (first_name, 1, 1) HAVING COUNT (*) > 1 ORDER BY 2 DESC;
员工表。 在同一部门工作并获得相同薪水的员工有多少?
解决方案 SELECT department_id, salary, COUNT (*) FROM employees GROUP BY department_id, salary HAVING COUNT (*) > 1;
员工表。 获取有关一周中每天有多少雇员被雇用的报告。 按数量排序
解决方案 SELECT TO_CHAR (hire_Date, 'Day') day, COUNT (*) FROM employees GROUP BY TO_CHAR (hire_Date, 'Day') ORDER BY 2 DESC;
员工表。 获取有关每年雇用多少员工的报告。 按数量排序
解决方案 SELECT TO_CHAR (hire_date, 'YYYY') year, COUNT (*) FROM employees GROUP BY TO_CHAR (hire_date, 'YYYY');
员工表。 获取有员工的部门数
解决方案 SELECT COUNT (COUNT (*)) department_count FROM employees WHERE department_id IS NOT NULL GROUP BY department_id;
员工表。 获取拥有30名以上员工的department_id列表
解决方案 SELECT department_id FROM employees GROUP BY department_id HAVING COUNT (*) > 30;
员工表。 获取department_id的列表以及每个部门员工的四舍五入平均工资。
解决方案 SELECT department_id, ROUND (AVG (salary)) avg_salary FROM employees GROUP BY department_id;
国家表。 获取一个region_id列表,其中所有country_name的所有字母之和超过60
解决方案 SELECT region_id FROM countries GROUP BY region_id HAVING SUM (LENGTH (country_name)) > 60;
员工表。 获取Department_id的列表,其中有多个(> 1)job_id的员工在其中工作
解决方案 SELECT department_id FROM employees GROUP BY department_id HAVING COUNT (DISTINCT job_id) > 1;
员工表。 获取下级人数大于5并且下级所有薪金总和大于50,000的manager_id的列表
解决方案 SELECT manager_id FROM employees GROUP BY manager_id HAVING COUNT (*) > 5 AND SUM (salary) > 50000;
员工表。 获取一份manager_id列表,其所有下属的平均薪水在6000到9000之间且没有领取奖金(commission_pct为空)
解决方案 SELECT manager_id, AVG (salary) avg_salary FROM employees WHERE commission_pct IS NULL GROUP BY manager_id HAVING AVG (salary) BETWEEN 6000 AND 9000;
员工表。 从所有以单词“ CLERK”结尾的job_id中获取最高薪水
解决方案 SELECT MAX (salary) max_salary FROM employees WHERE job_id LIKE '%CLERK'; SELECT MAX (salary) max_salary FROM employees WHERE SUBSTR (job_id, -5) = 'CLERK';
员工表。 获得部门所有平均薪水中的最高薪水
解决方案 SELECT MAX (AVG (salary)) FROM employees GROUP BY department_id;
员工表。 获取名称中字母数相同的员工数。 同时,仅显示名称长度大于5且名称大于或等于20的员工。
解决方案 SELECT LENGTH (first_name), COUNT (*) FROM employees GROUP BY LENGTH (first_name) HAVING LENGTH (first_name) > 5 AND COUNT (*) > 20 ORDER BY LENGTH (first_name); SELECT LENGTH (first_name), COUNT (*) FROM employees WHERE LENGTH (first_name) > 5 GROUP BY LENGTH (first_name) HAVING COUNT (*) > 20 ORDER BY LENGTH (first_name);
使用联接从多个表显示数据员工,部门,位置,国家/地区,地区表。 获取地区列表以及每个地区的员工人数
解决方案 SELECT region_name, COUNT (*) FROM employees e JOIN departments d ON (e.department_id = d.department_id) JOIN locations l ON (d.location_id = l.location_id) JOIN countries c ON (l.country_id = c.country_id) JOIN regions r ON (c.region_id = r.region_id) GROUP BY region_name;
员工,部门,位置,国家/地区,地区表。 获取有关每个员工的详细信息:
名,姓,部门,工作,街道,国家/地区,地区
解决方案 SELECT First_name, Last_name, Department_name, Job_id, street_address, Country_name, Region_name FROM employees e JOIN departments d ON (e.department_id = d.department_id) JOIN locations l ON (d.location_id = l.location_id) JOIN countries c ON (l.country_id = c.country_id) JOIN regions r ON (c.region_id = r.region_id);
员工表。 显示所有拥有6名以上员工的经理
解决方案 SELECT man.first_name, COUNT (*) FROM employees emp JOIN employees man ON (emp.manager_id = man.employee_id) GROUP BY man.first_name HAVING COUNT (*) > 6;
员工表。 显示所有不向任何人汇报的员工
解决方案 SELECT emp.first_name FROM employees emp LEFT JOIN employees man ON (emp.manager_id = man.employee_id) WHERE man.FIRST_NAME IS NULL; SELECT first_name FROM employees WHERE manager_id IS NULL;
员工表Job_history。 Employee表存储所有员工。 Job_history表存储了离开公司的员工。 获取有关所有员工及其在公司中的状态的报告(工作或离开公司的日期为离职日期)
一个例子:
first_name | 状态
珍妮佛| 2006年12月31日离开公司
克拉拉| 目前正在工作
解决方案 SELECT first_name, NVL2 ( end_date, TO_CHAR (end_date, 'fm""Left the company at"" DD ""of"" Month, YYYY'), 'Currently Working') status FROM employees e LEFT JOIN job_history j ON (e.employee_id = j.employee_id);
员工,部门,位置,国家/地区,地区表。 获取居住在欧洲的员工列表(region_name)
解决方案 SELECT first_name FROM employees JOIN departments USING (department_id) JOIN locations USING (location_id) JOIN countries USING (country_id) JOIN regions USING (region_id) WHERE region_name = 'Europe'; SELECT first_name FROM employees e JOIN departments d ON (e.department_id = d.department_id) JOIN locations l ON (d.location_id = l.location_id) JOIN countries c ON (l.country_id = c.country_id) JOIN regions r ON (c.region_id = r.region_id) WHERE region_name = 'Europe';
员工表,部门。 显示拥有30名以上员工的所有部门
解决方案 SELECT department_name, COUNT (*) FROM employees e JOIN departments d ON (e.department_id = d.department_id) GROUP BY department_name HAVING COUNT (*) > 30;
员工表,部门。 显示所有不在任何部门的员工
解决方案 SELECT first_name FROM employees e LEFT JOIN departments d ON (e.department_id = d.department_id) WHERE d.department_name IS NULL; SELECT first_name FROM employees WHERE department_id IS NULL;
员工表,部门。 显示没有一个员工的所有部门
解决方案 SELECT department_name FROM employees e RIGHT JOIN departments d ON (e.department_id = d.department_id) WHERE first_name IS NULL;
员工表。 显示所有没有下属的员工
解决方案 SELECT man.first_name FROM employees emp RIGHT JOIN employees man ON (emp.manager_id = man.employee_id) WHERE emp.FIRST_NAME IS NULL;
表员工,工作,部门。 以以下格式显示员工:名字,职位名称,部门名称。
一个例子:
名| 职位名称| 部门名称
唐纳德| 运输 职员运输
解决方案 SELECT first_name, job_title, department_name FROM employees e JOIN jobs j ON (e.job_id = j.job_id) JOIN departments d ON (d.department_id = e.department_id);
员工表。 获取其经理在2005年找到工作的员工列表,但与此同时,这些员工自己在2005年之前得到工作
解决方案 SELECT emp.* FROM employees emp JOIN employees man ON (emp.manager_id = man.employee_id) WHERE TO_CHAR (man.hire_date, 'YYYY') = '2005' AND emp.hire_date < TO_DATE ('01012005', 'DDMMYYYY');
员工表。 获取其经理在任何一年的一月内获得工作并且这些雇员的job_title长度超过15个字符的雇员的列表
解决方案 SELECT emp.* FROM employees emp JOIN employees man ON (emp.manager_id = man.employee_id) JOIN jobs j ON (emp.job_id = j.job_id) WHERE TO_CHAR (man.hire_date, 'MM') = '01' AND LENGTH (j.job_title) > 15;
使用子查询解决查询员工表。 获取名称最长的员工列表。
解决方案 SELECT * FROM employees WHERE LENGTH (first_name) = (SELECT MAX (LENGTH (first_name)) FROM employees);
员工表。 获取薪水高于所有员工平均薪水的员工列表
解决方案 SELECT * FROM employees WHERE salary > (SELECT AVG (salary) FROM employees);
表员工,部门,位置。 建立一个员工收入总额较少的城市。
解决方案 SELECT city FROM employees e JOIN departments d ON (e.department_id = d.department_id) JOIN locations l ON (d.location_id = l.location_id) GROUP BY city HAVING SUM (salary) = ( SELECT MIN (SUM (salary)) FROM employees e JOIN departments d ON (e.department_id = d.department_id) JOIN locations l ON (d.location_id = l.location_id) GROUP BY city);
员工表。 获取其经理的薪水超过15,000的员工列表。
解决方案 SELECT * FROM employees WHERE manager_id IN (SELECT employee_id FROM employees WHERE salary > 15000)
员工表,部门。 显示没有一个员工的所有部门
解决方案 SELECT * FROM departments WHERE department_id NOT IN (SELECT department_id FROM employees WHERE department_id IS NOT NULL);
员工表。 显示所有不是经理的员工
解决方案 SELECT * FROM employees WHERE employee_id NOT IN (SELECT manager_id FROM employees WHERE manager_id IS NOT NULL)
员工表。 显示所有拥有6名以上员工的经理
解决方案 SELECT * FROM employees e WHERE (SELECT COUNT (*) FROM employees WHERE manager_id = e.employee_id) > 6;
员工表,部门。 显示在IT部门工作的员工
解决方案 SELECT * FROM employees WHERE department_id = (SELECT department_id FROM departments WHERE department_name = 'IT');
表员工,工作,部门。 以以下格式显示员工:名字,职位名称,部门名称。
一个例子:
名| 职位名称| 部门名称
唐纳德| 运输 职员运输
解决方案 SELECT first_name, (SELECT job_title FROM jobs WHERE job_id = e.job_id) job_title, (SELECT department_name FROM departments WHERE department_id = e.department_id) department_name FROM employees e;
员工表。 获取其经理在2005年找到工作的员工列表,但与此同时,这些员工自己在2005年之前得到工作
解决方案 SELECT * FROM employees WHERE manager_id IN (SELECT employee_id FROM employees WHERE TO_CHAR (hire_date, 'YYYY') = '2005') AND hire_date < TO_DATE ('01012005', 'DDMMYYYY');
员工表。 获取其经理在任何一年的一月内获得工作并且这些雇员的job_title长度超过15个字符的雇员的列表
解决方案 SELECT * FROM employees e WHERE manager_id IN (SELECT employee_id FROM employees WHERE TO_CHAR (hire_date, 'MM') = '01') AND (SELECT LENGTH (job_title) FROM jobs WHERE job_id = e.job_id) > 15;
现在就这些了。我希望任务有趣而有趣。
如果可能,我将补充此任务列表。
我也很高兴有任何意见和建议。
PS:如果有人提出了有趣的SELECT任务,请在注释中写上,然后添加到列表中。
谢谢啦