2012-07-25 93 views
0

員工可以在很多部門工作,而且每個部門可以有很多員工。因此需要一個關係表關係表上的SQL查詢

表:
EMP(EID,爲ename,EAGE,esalary)
工程(EID,確實,pct_time)
部門(確實,DNAME,預算,經理ID)

找到所有在這兩種軟件工作的員工和硬件:

SELECT e.ename FROM EMP e, Works w, Dept d 
WHERE e.eid = w.eid AND w.did = d.did AND d.did = 
(SELECT did FROM dept WHERE dname = 'Hardware' OR 'Software') 

按喬恩:

SELECT e.ename FROM EMP e OR Works w OR Dept d 
WHERE e.eid = w.eid AND w.did = d.did AND d.did = 
(SELECT did FROM dept WHERE dname = 'Hardware' OR 'Software') 

而我只是不知道如何確保在同一個eid下的硬件和軟件的Works中有兩個條目。

+0

您的'從僱主或工作部門或者部門'語法是標準SQL符號上的一項創新。我擔心你正在使用的DBMS可能會對語法採取異常並拒絕你的SQL語句。 – 2012-07-25 03:34:22

回答

1
select e.name 
    from emp e, works h_w, dept h_d, works s_w, dept s_d 
where e.eid = h_w.eid 
    and e.eid = s_w.eid 
    and h_w.did = h_d.did 
    and h_d.dname = 'Hardware' 
    and s_w.did = s_d.did 
    and s_d.dname = 'Software' 
+0

哇,這是偉大的信息,我不知道你可以用不同的名字別名相同的表。 – KevinCameron1337 2012-07-25 03:07:35

+0

通常,您應該在FROM子句中使用'現代'(意思是1992年後)的SQL標準JOIN表示法,而不是'古代'(意思是1992年以前)以逗號分隔的表名列表。 – 2012-07-25 03:23:40

+0

像我在編輯中所做的那樣? – KevinCameron1337 2012-07-25 03:32:19

1

這裏是你如何解決這個問題的步驟:

  • 首先,獲取的所有行works表所在的部門是無論是硬件或軟件
  • 然後對於任何員工來說,如果存在兩行,這意味着他/她在兩個部門工作。
  • 對於任何員工,如果少於兩行的存在,這意味着他/她只能爲兩者中的一員工作,或者根本不工作。
  • 我們需要檢索具有兩行的員工。

所以我們可以首先要做的就是從works表中選擇,加入其對dept表,並篩選出不屬於硬件或軟件的任何部門:

SELECT a.* 
FROM works a 
INNER JOIN dept b ON a.did = b.did 
WHERE b.dname IN ('Hardware','Software') 

那麼,想什麼do是由每個員工分組的,這將使我們能夠訪問聚合信息,例如每位員工的行數或sum/max/min/avg /等。其他欄目。我們必須以計數的工作:

SELECT a.eid 
FROM works a 
INNER JOIN dept b ON a.did = b.did 
WHERE b.dname IN ('Hardware','Software') 
GROUP BY a.eid 
HAVING COUNT(1) = 2 

這給了我們只有eid S作正是兩行(即適用於軟件和硬件部門)。

eids是不夠的。我們希望有關員工的整個信息,所以我們必須換行整個查詢,並加入其對員工表來獲取其信息的休息:

SELECT a.* 
FROM emp a 
INNER JOIN 
(
    SELECT a.eid 
    FROM works a 
    INNER JOIN dept b ON a.did = b.did 
    WHERE b.dname IN ('Hardware','Software') 
    GROUP BY a.eid 
    HAVING COUNT(1) = 2 
) b ON a.eid = b.eid 

有你有它:員工誰工作在軟件和硬件部門。您可以單獨執行上面的每個查詢,查看我們如何到達最終解決方案的中間步驟。

+0

現在很清楚,我明白了,但我不認爲我會自己想出來。雖然,當我通過這個進展時,我可能需要其中一些技術來解決其他問題。非常感謝。 – KevinCameron1337 2012-07-25 03:20:38

1

下面是查詢的另一種表述:

SELECT e.* 
    FROM emp AS e 
    JOIN (SELECT w.eid 
      FROM works AS w JOIN dept AS d 
      ON d.did = w.did AND d.dname = 'Software') AS s 
    ON s.eid = e.eid 
    JOIN (SELECT w.eid 
      FROM works AS w JOIN dept AS d 
      ON d.did = w.did AND d.dname = 'Hardware') AS h 
    ON h.eid = e.eid 

這有兩個對稱的子查詢,一個生成的軟件部門的員工ID,爲硬件部門的一個發電員工ID。選定的員工是那些在兩個部門都列有ID的人(因爲他們都是內部連接)。

+0

別名s和h給你處理SELECT查詢的結果嗎?我發現這是最難遵循的一個。 – KevinCameron1337 2012-07-25 03:37:12

+0

'AS s'有效地將查詢的結果命名爲's'(就像它是一個表或視圖一樣),同樣用'AS h'和它的查詢命名。如果你沒有學過JOIN註釋,那麼這可能會更困難,但(IMNSHO)在學校沒有教你加入註釋。有很多原因爲什麼他們比舊式標記更好。 – 2012-07-25 03:48:20