2013-02-08 86 views
0

Folks, 所有我期望的是擴展INNER JOIN。讓我談談點。我有兩個表部門& Emp。一個部門可以有多個Emp的&而不是其他方式。SQL INNER JOIN僅在第一次匹配時返回父行值

 
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 

希望我傳達了我想要的東西。它只是一個常規的內部加入的外鍵約束。但是,我希望第一個表(Dept)中的值是NULL-ed,除了第一個匹配。話雖如此,我不在乎第一場比賽是什麼。請看下面 - 只是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. 

在此先感謝。儘管它是一個簡單的例子,但對於很長的解釋抱歉。

+0

你會嘗試左連接嗎? – DevelopmentIsMyPassion 2013-02-08 17:24:25

+2

左連接不會得到他們正在尋找的結果。看起來更像他們試圖對結果進行分組,並且只允許Dept_id和Dept_name中每個部門的第一個匹配的值。我很好奇你爲什麼要這麼做,因爲這會讓數據顯示吉爾吉姆和賈瑞特沒有任何部門。正確的做法是獲得所有列中的值,並處理代碼中用於顯示結果的格式。隨着所要求的內容,如果你改變客戶端上的排序,你將有不可讀的數據 – TimWagaman 2013-02-08 17:29:16

+0

你是對的。這是一個瘋狂的查詢。我正在嘗試做一個我的應用程序應該做的部分。但是,我確信有一種方法可以通過查詢來完成並且想知道這一點。感謝評論。 – Yogi 2013-02-08 17:51:56

回答

5

我帶IC同意。這是,這似乎是做一些應用程序應該做的,而不是你的SQL查詢,話雖如此瘋狂的查詢,它的樂趣,寫這些查詢:)

SELECT CASE WHEN RowNumber = 1 THEN Dept_id ELSE NULL END AS Dept_id, 
     CASE WHEN RowNumber = 1 THEN Dept_name ELSE NULL END AS Dept_name, 
     Emp_id, Emp_Name 
FROM Dept d 
INNER JOIN 
(SELECT ROW_NUMBER() OVER (PARTITION BY Dept_id ORDER BY Emp_Name) AS RowNumber, 
     Dept_id, Dept_name, Emp_id, Emp_Name 
FROM Emp) t on t.Dept_id = d. Dept_id 
+0

我想這是針對某種「ASCII報告」 – 2013-02-08 17:35:02

+0

@a_horse_with_no_name我想可能會出現這種情況,這確實是最好的辦法! – 2013-02-08 17:37:26

+0

這就是我想要的。感謝Bassam。 – Yogi 2013-02-08 17:57:10

1

老實說,我不確定你爲什麼要這個結果。格式化通常最好留給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 

SQL Fiddle Demo

1
select case 
      when lag(d.dept_id) over (partition by d.dept_id order by e.emp_id) = d.dept_id then null 
      else d.dept_id 
     end as dept_id, 
     case 
      when lag(d.dept_name) over (partition by d.dept_id order by e.emp_id) = d.dept_name then null 
      else d.dept_name 
     end as dept_name, 
     e.emp_id, 
     e.emp_name 
from dept d 
    join emp e on e.dept_id = d.dept_id 
order by d.dept_id, d.dept_name, e.emp_id 
0

正如我提到的我上面的評論,我不確定你是否真的希望結果以你問的方式返回。考慮這一點。如果結果集導出到Excel,並且用戶更改了排序,那麼您將失去部門員工1-x所在的位置,並且員工0仍會顯示其部門。我建議你按Dept_id分組,並且不要將dept_id和dept_name清零。在顯示代碼中處理該數據的顯示。

0
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" 
0

,因爲我想不出你會想,其他則報告的目的,那麼你也可以通過使用SQL * Plus formmating這樣做的一個原因。

在SQL *查詢加

break on dept_id skip 1 

享受之前只需要運行下面的命令。