掌握SQL基础:(第2部分)

数据库系列(5部分)
📝 面向新手的DBMS面试题
📝 面向新手的10大SQL查询
掌握SQL基础:(第2部分)
掌握SQL基础:(第1部分)
掌握SQL连接查询:HR员工数据分析
欢迎来到我们SQL子查询系列的第2部分,我们将深入探讨利用子查询从HR数据库中获得强大洞察。
在本博客中,我们专注于一个实用的员工管理系统,包含员工和部门表。我们将介绍模式、插入示例数据,并演示42个高级SQL查询,强调子查询来解决复杂的HR和业务场景。本指南非常适合数据分析师、HR专业人员或开发者,他们希望通过真实世界的示例来提高SQL技能。
🧩 数据库架构概览
tbl_emp:存储员工详细信息
列:
emp_id
emp_name
street_address
city
salary
commission
job
deptno
hiredate
company_name
tbl_department:包含部门信息
列:
deptno
dept_name
🏗️ 创建表
  1. CREATE TABLE tbl_department (
  2. deptno INT PRIMARY KEY,
  3. dept_name VARCHAR(50)
  4. );

  5. CREATE TABLE tbl_emp (
  6. emp_id INT PRIMARY KEY,
  7. emp_name VARCHAR(50),
  8. street_address VARCHAR(100),
  9. city VARCHAR(50),
  10. salary DECIMAL(10,2),
  11. commission DECIMAL(10,2),
  12. job VARCHAR(50),
  13. deptno INT,
  14. hiredate DATE,
  15. company_name VARCHAR(100),
  16. FOREIGN KEY (deptno) REFERENCES tbl_department(deptno)
  17. );
sql
📝 插入示例数据
  1. INSERT INTO tbl_department (deptno, dept_name) VALUES
  2. (10, 'Sales'),
  3. (20, 'HR'),
  4. (30, 'IT'),
  5. (40, 'Finance'),
  6. (50, 'Marketing');

  7. INSERT INTO tbl_emp (emp_id, emp_name, street_address, city, salary, commission, job, deptno, hiredate, company_name) VALUES
  8. (1, 'Amit Sharma', '123 MG Road', 'Delhi', 12000.00, 500.00, 'Salesman', 10, '2015-06-10', 'First Bank Corporation'),
  9. (2, 'Priya Verma', '456 Park Avenue', 'Mumbai', 25000.00, 2000.00, 'Manager', 20, '2012-08-15', 'First Bank Corporation'),
  10. (3, 'Rajesh Kumar', '789 Green Street', 'Bangalore', 18000.00, 1500.00, 'Salesman', 30, '2016-02-20', 'Second Bank Corporation'),
  11. (4, 'Anjali Gupta', '321 Ocean Drive', 'Chennai', 9500.00, 0.00, 'Clerk', 10, '2018-07-10', 'First Bank Corporation'),
  12. (5, 'Vikram Singh', '654 Palm Street', 'Delhi', 22000.00, 3000.00, 'Salesman', 10, '2014-04-01', 'First Bank Corporation'),
  13. (6, 'Rina Patel', '987 Sunset Boulevard', 'Ahmedabad', 13000.00, 0.00, 'Clerk', 20, '2017-05-23', 'First Bank Corporation'),
  14. (7, 'Manoj Desai', '852 Elm Street', 'Mumbai', 30000.00, 3500.00, 'Manager', 30, '2010-01-12', 'Second Bank Corporation'),
  15. (8, 'Sonia Reddy', '741 Maple Lane', 'Hyderabad', 15000.00, 1000.00, 'Salesman', 30, '2019-11-02', 'First Bank Corporation'),
  16. (9, 'Sandeep Jain', '258 High Street', 'Kolkata', 20000.00, 2500.00, 'Manager', 40, '2011-03-22', 'First Bank Corporation'),
  17. (10, 'Neha Kapoor', '963 River Road', 'Pune', 27000.00, 1500.00, 'Clerk', 50, '2013-09-14', 'Second Bank Corporation');
sql
🔍 高级SQL子查询练习
1. First Bank Corporation中收入超过10,000美元的员工
  1. SELECT * FROM tbl_emp
  2. WHERE company_name = 'First Bank Corporation' AND salary > 10000;
sql
2. 选择部门30中的员工
  1. SELECT * FROM tbl_emp
  2. WHERE deptno = 30;
sql
3. 列出所有文员的姓名、编号和部门
  1. SELECT emp_name, emp_id, deptno FROM tbl_emp
  2. WHERE job = 'Clerk';
sql
4. 部门编号大于20的员工的部门编号和名称
  1. SELECT DISTINCT d.deptno, d.dept_name
  2. FROM tbl_emp e
  3. JOIN tbl_department d ON e.deptno = d.deptno
  4. WHERE d.deptno > 20;
sql
5. 佣金大于工资的员工
  1. SELECT * FROM tbl_emp
  2. WHERE commission > salary;
sql
6. 佣金大于工资60%的员工
  1. SELECT * FROM tbl_emp
  2. WHERE commission > salary * 0.6;
sql
7. 列出部门20中收入超过2000的所有员工的姓名、工作和工资
  1. SELECT emp_name, job, salary FROM tbl_emp
  2. WHERE deptno = 20 AND salary > 2000;
sql
8. 部门30中工资超过1,500美元的销售员
  1. SELECT * FROM tbl_emp
  2. WHERE deptno = 30 AND job = 'Salesman' AND salary > 1500;
sql
9. 经理或总裁的员工
  1. SELECT * FROM tbl_emp
  2. WHERE job='Manager' or job='President';
sql
10. 不在部门30的经理
  1. SELECT * FROM tbl_emp
  2. WHERE job = 'Manager' AND deptno != 30;
sql
11. 部门10中的经理和文员
  1. SELECT * FROM tbl_emp
  2. WHERE deptno = 10 AND job IN ('Manager', 'Clerk');
sql
12. 经理(任何部门)和部门20中的文员
  1. SELECT * FROM tbl_emp
  2. WHERE job = 'Manager' OR (job = 'Clerk' AND deptno = 20);
sql
13. 查找部门10中所有经理的详细信息、部门20中所有文员的详细信息,以及既不是经理也不是文员但工资大于等于2000的所有员工
  1. SELECT * FROM tbl_emp
  2. WHERE (job = 'Manager' AND deptno = 10)
  3. OR (job = 'Clerk' AND deptno = 20)
  4. OR (job NOT IN ('Manager', 'Clerk') AND salary >= 2000);
sql
14. 查找部门20中既不是经理也不是文员的任何人姓名
  1. SELECT emp_name FROM tbl_emp
  2. WHERE deptno = 20 AND job NOT IN ('Manager', 'Clerk');
sql
15. 收入在1200到1400之间的员工
  1. SELECT * FROM tbl_emp
  2. WHERE salary BETWEEN 1200 AND 1400;
sql
16. 查找是文员、分析师或销售员的员工
  1. SELECT * FROM tbl_emp
  2. WHERE job IN ('Clerk', 'Analyst', 'Salesman');
sql
17. 查找不是文员、分析师或销售员的员工
  1. SELECT * FROM tbl_emp
  2. WHERE job NOT IN ('Clerk', 'Analyst', 'Salesman');
sql
18. 查找工资大于2000且佣金大于200的员工
  1. SELECT * FROM tbl_emp
  2. WHERE salary > 2000 AND commission > 200;
sql
19. 查找工资大于2000或佣金大于200的员工
  1. SELECT * FROM tbl_emp
  2. WHERE salary > 2000 OR commission > 200;
sql
20. 查找工资大于2000且佣金大于200的员工,或者工资大于2000且佣金为0的员工
  1. SELECT * FROM tbl_emp
  2. WHERE (salary > 2000 AND commission > 200)
  3. OR (salary > 2000 AND commission = 0);
sql
21. 查找姓名以'A'开头的员工
  1. SELECT emp_name
  2. FROM tbl_emp
  3. WHERE emp_name LIKE 'A%';
sql
22. 查找姓名以'A'结尾的员工
  1. SELECT emp_name
  2. FROM tbl_emp
  3. WHERE emp_name LIKE '%A';
sql
23. 查找姓名以'M'开头或结尾的所有员工
  1. SELECT emp_name
  2. FROM tbl_emp
  3. WHERE emp_name LIKE 'M%' OR emp_name LIKE '%M';
sql
24. 查找姓名中包含字母'M'的所有员工(不区分大小写)
  1. SELECT emp_name
  2. FROM tbl_emp
  3. WHERE emp_name LIKE '%M%' OR emp_name LIKE '%m%';
sql
25. 查找姓名最多15个字符且姓名第3个字符为'R'的所有员工
  1. SELECT emp_name
  2. FROM tbl_emp
  3. WHERE LENGTH(emp_name) <= 15 AND emp_name LIKE '__R%';
sql
26. 查找在2月份(任何年份)被雇佣的所有员工
  1. SELECT emp_name
  2. FROM tbl_emp
  3. WHERE MONTH(hiredate) = 2;
sql
27. 查找在月末被雇佣的所有员工
  1. SELECT emp_name
  2. FROM tbl_emp
  3. WHERE LAST_DAY(hiredate) = hiredate;
sql
28. 查找2年多前被雇佣的所有员工
  1. SELECT emp_name
  2. FROM tbl_emp
  3. WHERE hiredate < CURDATE() - INTERVAL 2 YEAR;
sql
29. 查找2003年被雇佣的经理
  1. SELECT emp_name
  2. FROM tbl_emp
  3. WHERE job = 'Manager' AND YEAR(hiredate) = 2003;
sql
30. 显示所有员工的姓名和工作,用空格分隔
  1. SELECT CONCAT(emp_name, ' ', job) AS name_and_job
  2. FROM tbl_emp;
sql
31. 显示所有员工的姓名,右对齐到15个字符
  1. SELECT LPAD(emp_name, 15, ' ') FROM tbl_emp;
sql
*32. 显示所有员工的姓名,用''右填充到15个字符
  1. SELECT RPAD(emp_name, 15, '*') FROM tbl_emp;
sql
33. 显示所有员工的姓名,去掉前导'A'
  1. SELECT TRIM(LEADING 'A' FROM emp_name) FROM tbl_emp;
sql
34. 显示所有员工的姓名,去掉尾随'R'
  1. SELECT TRIM(TRAILING 'R' FROM emp_name) FROM tbl_emp;
sql
35. 显示所有员工姓名的前3个和后3个字符
  1. SELECT CONCAT(LEFT(emp_name, 3), RIGHT(emp_name, 3)) AS first_last_chars
  2. FROM tbl_emp;
sql
36. 显示所有员工的姓名,将'A'替换为'a'
  1. SELECT REPLACE(emp_name, 'A', 'a') FROM tbl_emp;
sql
37. 显示所有员工的姓名和姓名中字符串'AR'出现的位置
  1. SELECT emp_name, POSITION('AR' in emp_name) AS position
  2. FROM tbl_emp;
sql
38. 显示所有员工的工资,四舍五入到最接近的1000卢比
  1. SELECT emp_name, ROUND(salary, -3) AS rounded_salary
  2. FROM tbl_emp;
sql
39. 显示员工的姓名、工作和工资,按工作和工资排序
  1. SELECT emp_name, job, salary
  2. FROM tbl_emp
  3. ORDER BY job, salary;
sql
40. 显示员工的姓名、工作和工资,按工作降序排序,在工作内按工资排序
  1. SELECT emp_name, job, salary
  2. FROM tbl_emp
  3. ORDER BY job DESC, salary ASC;
sql
41. 列出已完成1年服务的员工的姓名、部门名称和工资
  1. SELECT e.emp_name, d.dept_name, e.salary
  2. FROM tbl_emp e
  3. JOIN tbl_department d ON e.deptno = d.deptno
  4. WHERE e.hiredate <= DATE_SUB(CURDATE(), INTERVAL 1 YEAR);
sql
42. 列出2003年加入的员工的姓名、部门名称和雇佣日期。按加入日期排序输出
  1. SELECT e.emp_name, d.dept_name, e.hiredate
  2. FROM tbl_emp e
  3. JOIN tbl_department d ON e.deptno = d.deptno
  4. WHERE YEAR(e.hiredate) = 2003
  5. ORDER BY e.hiredate;
sql
🏁 结论
我们SQL子查询系列的第2部分展示了高级查询来提取关键的HR洞察,重点关注用于复杂过滤和比较的子查询。
从分析员工收入到跟踪雇佣日期和姓名模式,这些查询展示了SQL在HR数据管理中的强大功能。
使用这些示例作为基础来构建你自己的查询并推动明智的业务决策。
关键词:SQL、数据库、教程、初学者、子查询、HR数据分析