编写没有UNION或任何JOIN的SQL查询(FULL / LEFT / RIGHT)

时间:2017-12-01 19:14:43

标签: sql postgresql

作为我的数据库主题的每周练习,我有3个表。班级,部门和员工,我需要列出与员工和部门名称对应的班级名称。部门名称是物品所在的部门。问题是有一些员工没有住在任何部门,所以他们的列值为空。

表的主要结构:

  • 员工(staffid(主键),姓名,deptid,年龄)
  • 班级(classid(主键),姓名,meetat,room,staffid)
  • 部门(deptid(主键),姓名)
 +------------------------+
 | class || staff|| dep   |
 +------------------------+
 |  A    || 1    ||  L    |
 |  B    || 2    ||  G    |
 |  C    || 3    ||       |
 |  D    || 4    ||  L    |
 +------------------------+

这就是我想要实现的目标。 department_name为null的工作人员必须保持为空。

SELECT DISTINCT c.name AS "class_name" , st.name AS "staff_name", d.name AS "department_name" 
 FROM class c, staff st, department d
 WHERE c.staffid = st.staffid AND st.deptid = d.deptid
 UNION 
SELECT DISTINCT class.name AS "class_name", staff.name AS "staff_name" , NULL AS "department_name" FROM staff staff, class class, department d WHERE staff.deptid IS NULL AND staff.staffid = class.staffid;

此查询完美无缺。但只能使用UNION关键字。如何使用相关子查询获得相同的结果? (不能使用JOIN关键字)

我尝试使用这样的查询:

SELECT DISTINCT c.name AS "class_name" , st.name AS "staff_name", d.name AS "department_name" 
 FROM class c, staff st, department d
 WHERE (c.staffid = st.staffid AND st.deptid = d.deptid AND d.deptid IS NOT NULL) OR NOT EXISTS (SELECT DISTINCT NULL AS "department_name" FROM staff staff, class class, department d WHERE staff.deptid IS NOT NULL AND staff.staffid = class.staffid); 

但是这些查询并没有向我显示值为null的任何部门,只显示包含名称的部门。

如何使用不带JOIN / UNION关键字的子查询来表达这一点?

编辑:伙计们,我知道可能有更好的方法来解决这个问题。正如我在开始时说的,这是一次大学练习,我们的教授希望我们解决这个问题。我们很快就会了解JOIN。

2 个答案:

答案 0 :(得分:0)

SELECT

后面使用子查询
SELECT c.name AS "class_name" , 
       st.name AS "staff_name", 
       (SELECT d.name FROM department d WHERE st.deptid = d.deptid) AS "department_name" 
FROM class c, staff st
WHERE c.staffid = st.staffid

select后面的子查询必须始终返回一个值(因为员工属于一个部门)。如果工作人员不属于任何人员,则返回NULL并且结果中没有消除工作人员(与内部联接相比)。

即使没有旧的连接语法也可以解决它,但是,这是非常模糊的解决方案:)

SELECT c.name AS "class_name" , 
       (SELECT st.name FROM staff st WHERE c.staffid = st.staffid) AS "staff_name", 
       (SELECT
          (SELECT d.name FROM department d WHERE st.deptid = d.deptid)
        FROM staff st WHERE c.staffid = st.staffid
       ) AS "department_name" 
FROM class c

答案 1 :(得分:0)

学习使用正确的,明确的JOIN语法。切勿在{{1​​}}子句中使用逗号。

然后,你可能马上就认识到你需要一个FROM

LEFT JOIN

我怀疑是否需要SELECT DISTINCT c.name AS class_name, st.name AS staff_name" d.name AS department_name FROM class c LEFT JOIN staff st ON c.staffid = st.staffid LEFT JOIN department d ON st.deptid = d.deptid; 。但是我把它留下了,因为你比我更了解数据。