SELECT department_id FROM dmhr.dept EXCEPTSELECT department_id FROM dmhr.employee;
输出结果:
EXCEPT 获取第一个结果集的数据,然后排除第二个结果集的数据,类似减法运算。
IN、NOT IN、EXISTS
查询含有 null 值的行时,如果包含 IN、NOT IN 要注意两者的区别。IN 相当于 OR, 而 NOT IN 相当于 AND。示例语句如下所示:
SELECT * FROM dmhr.employee WHERE employee_id IN (1002, 1005, NULL);
返回 2 行数据记录,示例语句如下所示:
SELECT * FROM dmhr.employee WHERE employee_id NOTIN (1002, 1005, NULL);
返回记录为空,因为 NOT IN 的逻辑是 1002 AND 1005 AND NULL。当 NOT IN 后面跟的子查询返回的列存在 NULL 值,可能得不到正确的结果。
例如,查找员工所在部门编号,在部门表中不存在的数据。
数据准备,示例语句如下所示:
CREATETABLE dmhr.emp AS SELECT employee_id, employee_name, identity_card, salary, department_id FROM dmhr.employee WHERE employee_id IN (1109,1110,1111,1112,1113);
UPDATE dmhr.emp SET department_id = 999 WHERE employee_id = 1112;
UPDATE dmhr.emp SET department_id = NULL WHERE employee_id = 1113;
COMMIT;
员工表
部门表
执行如下 SQL,返回结果为空。
SELECT * FROM dmhr.emp t WHERE t.department_id NOTIN (SELECT department_id FROM dmhr.dept);
执行如下 SQL,返回结果不为空。
SELECT * FROM dmhr.emp t WHERENOTEXISTS (SELECT1 FROM dmhr.dept t1 WHERE t.department_id = t1.department_id);
输出结果:
连接类型
连接包括:内连接、左连接、右连接、全连接、自连接 5 种类型,以上连接类型 DM 数据库都支持。
数据准备,示例语句如下所示:
CREATETABLE dmhr.join_emp AS SELECT employee_name, department_id FROM dmhr.employee WHERE employee_id IN ( SELECTMIN (employee_id) FROM dmhr.employee GROUPBY department_id) ANDROWNUM < 10;
INSERTINTO dmhr.join_emp VALUES ('DM2020', 999);
COMMIT;
SELECT * FROM dmhr.join_emp;
输出结果:
红框内标识为后续插入的记录。
内连接
结果完全满足连接条件的记录。例如,如需显示员工名称和对应的部门名称。
写法一:
SELECT je.employee_name, d.department_name FROM dmhr.join_emp je, dmhr.department d WHERE je.department_id = d.department_id;
写法二:
SELECT je.employee_name, d.department_name FROM dmhr.join_emp je JOIN dmhr.department d ON (je.department_id = d.department_id)
SELECT e.employee_id,e.employee_name,e.salary,e.department_id,e.salary * CASEWHEN eb.TYPE = 1THEN.1WHEN eb.TYPE = 2THEN.2ELSE.3END AS bonus FROM dmhr.employee e, dmhr.emp_bonus eb WHERE e.employee_id = eb.employee_id
输出结果:
聚合后,示例语句如下所示:
SELECT department_id, SUM (salary) AS total_sal, SUM (bonus) AS total_bonus FROM (SELECT e.employee_id,e.employee_name,e.salary,e.department_id,e.salary * CASE WHEN eb.TYPE = 1THEN.1 WHEN eb.TYPE = 2THEN.2 ELSE.3 END AS bonus FROM dmhr.employee e, dmhr.emp_bonus eb WHERE e.employee_id = eb.employee_id) y GROUPBY y.department_id
输出结果:
聚合后奖金总额正确,工资总额不对,应该为 38560。示例语句如下所示:
SELECTSUM (SALARY) FROM dmhr.employee WHERE employee_id IN (1137,1138,1139,1140);
SELECT department_id, SUM (salary) AS total_sal, SUM (bonus * salary) AS total_bonus FROM dmhr.employee e, ( SELECT employee_id, SUM ( CASE WHENTYPE = 1THEN.1 WHENTYPE = 2THEN.2 ELSE.3 END) AS bonus FROM dmhr.emp_bonus GROUPBY employee_id) eb WHERE e.employee_id = eb.employee_id GROUPBY e.department_id
输出结果:
聚集与外连接
若要返回所有部门员工的工资和奖金且奖金数据中只包含部门号为 105 的数据,使用 LEFT JOIN 可以实现。示例语句如下所示:
SELECT department_id, SUM (salary) AS total_sal, SUM (bonus * salary) AS total_bonus FROM dmhr.employee e LEFTJOIN ( SELECT employee_id, SUM ( CASE WHENTYPE = 1THEN.1 WHENTYPE = 2THEN.2 ELSE.3 END) AS bonus FROM dmhr.emp_bonus GROUPBY employee_id) eb ON e.employee_id = eb.employee_id GROUPBY e.department_id ORDERBY1;
输出结果:
比较两个表差异的全外连接
准备两张表,表一:水果表 (fruits);表二:颜色表 (colors)。示例语句如下所示:
// 创建水果表 CREATETABLE dmhr.fruits ( fruit VARCHAR (12), f_num NUMBER );