【问题标题】:Write SQL query without UNION or any JOIN (FULL/LEFT/RIGHT)编写没有 UNION 或任何 JOIN (FULL/LEFT/RIGHT) 的 SQL 查询
【发布时间】:2017-12-02 03:51:14
【问题描述】:

作为我的数据库主题的每周练习,我有 3 个表。班级、部门和教职员工,这里我需要列出教职员工和部门名称对应的班级名称。部门名称是东西所在的部门。问题是有些员工不住在任何部门,因此他们的列值为空。

表格的主要结构:

  • 员工(员工(主键)、姓名、部门、​​年龄)
  • Class(classid (Primary key), name, metat, room, staffid)
  • 部门(deptid(主键),名称)
 +------------------------+
 | class || staff|| dep   |
 +------------------------+
 |  A    || 1    ||  L    |
 |  B    || 2    ||  G    |
 |  C    || 3    ||       |
 |  D    || 4    ||  L    |
 +------------------------+

这就是我想要完成的。 department_name 为空的人员必须保持为空。

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。

【问题讨论】:

  • 您的所有查询中都有 DISTINCT 关键字是否有原因?
  • 为什么限制查询不使用JOIN 关键字?由于FROM 子句中的逗号,您的查询隐式使用JOIN,这是一种已被ANSI-92 标准弃用的做法(如在1992 年......超过25 年前) 并且应该在今天使用。一些 DBMS 甚至不再完全支持它……如果你的教授需要这个,挑战他们或离开课堂。绝对没有理由向任何人教授这种古老的语法。
  • 我会使用 join 并告诉任何给我评分的人我使用了最好的工具来完成这项工作
  • 正如我所说的,这是一个练习,伙计们。我的教授希望我们将它与子查询一起使用,问他为什么要这样做:D 这并不是说我们不会在课程中学习 JOIN(实际上这是下一个主题),他希望我们学习我认为的概念。他实际上是一个非常好的教授,就此而言^^
  • 请告诉你的教授,教授这种过时的连接语法是愚蠢的。无论您在 where 子句中使用古代隐式连接还是现代显式 JOIN 关键字,连接都是连接。如果他不相信你,请把他介绍给这些 cmets

标签: sql postgresql


【解决方案1】:

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

【讨论】:

  • 不使用连接就不能回答问题。使用旧语法并不能使其正确。 :)
  • 我的意思是关键字 JOIN 和任何组合,而不是连接本身先生。
  • @NumanTakács 阻止您使用 JOIN 一词但使用逗号 JOIN 代替的意义何在...?
【解决方案2】:

学习使用正确、明确的JOIN 语法。切勿在 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;

我怀疑SELECT DISTINCT 是否也需要。但我把它留了下来,因为你会比我更了解数据。

【讨论】:

    猜你喜欢
    • 2020-03-07
    • 2018-02-28
    • 1970-01-01
    • 2021-02-23
    • 2012-02-27
    • 2014-01-07
    相关资源
    最近更新 更多