SQL内部联接仅在第一次匹配时返回父行值

SQL内部联接仅在第一次匹配时返回父行值,sql,oracle,Sql,Oracle,各位, 我想要的就是扩展内部连接。让我开门见山。我有两张桌子,部门和Emp。一个部门可以有多个Emp,反之亦然 Table Dept Dept_id Dept_Name 1 IT 2 HR 3 Other Table Emp Emp_id Dept_id Emp_Name 11 1 John 12 1 Jill 13 2 Jack 14 3

各位, 我想要的就是扩展内部连接。让我开门见山。我有两张桌子,部门和Emp。一个部门可以有多个Emp,反之亦然

Table Dept Dept_id Dept_Name 1 IT 2 HR 3 Other Table Emp Emp_id Dept_id Emp_Name 11 1 John 12 1 Jill 13 2 Jack 14 3 Jared 15 1 Jim 16 1 Jarret 17 2 Jacob I need to JOIN it on Dept_id Expected Results Dept_id Dept_name Emp_id Emp_Name 1 IT 11 John NULL NULL 12 Jill NULL NULL 15 Jim NULL NULL 16 Jarret 2 HR 13 Jack NULL NULL 17 Jacob 3 Other 14 Jared 餐桌部 部门id部门名称 1它 2小时 3其他 表Emp Emp\U id部门id Emp\U名称 11.1约翰 12.1吉尔 13.2千斤顶 14.3贾里德 15.1吉姆 16.1 Jarret 17.2雅各布 我需要在部门id上加入它 预期结果 部门id部门名称Emp\U id Emp\U名称 是约翰 零12吉尔 零15吉姆 空16 Jarret 2小时13分机 空17雅各布 3其他14罐 希望我准确地表达了我想要的。它只是外键约束上的常规内部联接。但是,我希望第一个表(Dept)中的值除第一个匹配项外为空。尽管如此,我不在乎第一场比赛是什么。请参见下文-仅显示部门id 1的结果

Expected Results (Only for Dept_id = 1) It could be Dept_id Dept_name Emp_id Emp_Name 1 IT 11 John NULL NULL 12 Jill NULL NULL 15 Jim NULL NULL 16 Jarret OR Dept_id Dept_name Emp_id Emp_Name 1 IT 15 Jim NULL NULL 12 Jill NULL NULL 11 John NULL NULL 16 Jarret OR Two other possibilities. 预期结果(仅适用于部门id=1) 可能是 部门id部门名称Emp\U id Emp\U名称 是约翰 零12吉尔 零15吉姆 空16 Jarret 或 部门id部门名称Emp\U id Emp\U名称 我是吉姆 零12吉尔 约翰 空16 Jarret 或 另外两种可能性。
提前谢谢。抱歉,虽然这是一个简单的例子,但解释得太长了。

老实说,我不太清楚你为什么想要这个结果。格式化通常最好留给UI层,而不是数据库服务器。这样做会使数据看起来像每个部门的非第一员工实际上没有一个部门,并且从根本上破坏了客户机中的任何排序或编辑功能

但是,您可以尝试:

SELECT FormattedDept.Dept_id, FormattedDept.Dept_Name, Emp.Emp_id, Emp.Emp_Name
FROM Emp
LEFT OUTER JOIN
(
    SELECT Dept.Dept_id, Dept.Dept_Name, MIN(Emp_id) AS Emp_id
    FROM Dept
    INNER JOIN Emp ON Dept.Dept_id = Emp.Dept_id
    GROUP BY Dept.Dept_id, Dept.Dept_Name
) FormattedDept ON Emp.Dept_id = FormattedDept.Dept_id
    AND Emp.Emp_id = FormattedDept.Emp_id
ORDER BY Emp.Dept_id, Emp.Emp_id

我同意Ic的观点。这是一个疯狂的查询,它似乎在做应用程序应该做的事情,而不是sql查询,也就是说,编写这些查询很有趣:)


正如我在上面的评论中提到的,我不确定您是否真的希望结果以您要求的方式返回。考虑一下这个。如果结果集导出到Excel,并且用户更改了排序,则您将丢失dept employee 1-x所在的部门,而employee 0仍将显示其部门。我建议您按部门id分组,不要将部门id和部门名称置空。在显示代码中处理该数据的显示

WITH newRecord
AS
(
   SELECT "Emp_id", "Dept_id", "Emp_Name",
           ROW_NUMBER() OVER (PARTITION BY "Dept_id" ORDER BY "Emp_id" ASC) RN
   FROM Emp  
)
SELECT  CASE WHEN RN = 1 THEN b."Dept_id" ELSE NULL END AS "Dept_ID",
        CASE WHEN RN = 1 THEN b."Dept_Name" ELSE NULL END AS "Dept_Name",
        "Emp_id", "Emp_Name"
FROM    newRecord a 
        INNER JOIN Dept b ON a."Dept_id" = b."Dept_id"

因为我想不出一个原因,除了报表之外,您还可以使用SQL*Plus FormMatting来实现这一点

只需在SQL*Plus中的查询之前运行以下命令

break on dept_id skip 1

享受。

你会尝试“左键联接”吗?左键联接不会得到他们想要的结果。看起来他们更像是在尝试对结果进行分组,并且只允许每个部门在第一次匹配时使用Dept_id和Dept_name中的值。我很好奇为什么要这样做,因为这样会使数据显示Jill Jim和Jarret没有部门。正确的做法是在所有列中都有值,并处理代码中用于显示结果的格式。对于所询问的内容,如果您更改客户端的排序,您将拥有无法读取的数据,您是对的。这是一个疯狂的问题。我正在尝试做我的应用程序应该做的部分。但是,我确信有一种方法可以通过查询来实现&我想知道。谢谢你的评论。我想这是为了某种“ASCII报告”@a_horse_,没有名字。我想在某些情况下,这确实是最好的方法!这正是我想要的。谢谢Bassam。@Bassam-我知道CASE语句,但还不够好,无法使用分区与之结合。
WITH newRecord
AS
(
   SELECT "Emp_id", "Dept_id", "Emp_Name",
           ROW_NUMBER() OVER (PARTITION BY "Dept_id" ORDER BY "Emp_id" ASC) RN
   FROM Emp  
)
SELECT  CASE WHEN RN = 1 THEN b."Dept_id" ELSE NULL END AS "Dept_ID",
        CASE WHEN RN = 1 THEN b."Dept_Name" ELSE NULL END AS "Dept_Name",
        "Emp_id", "Emp_Name"
FROM    newRecord a 
        INNER JOIN Dept b ON a."Dept_id" = b."Dept_id"
break on dept_id skip 1