2016-12-02 169 views
1

我有兩個表:多個表選擇,子查詢返回多個值。 SQL

員工

id | fullName | birth  | speciality 
1 | A A A  | 01/01/1980 | Manager 
2 | B B B  | 01/01/1980 | Developer 
3 | C C C  | 01/01/1980 | User 

EmployeesStatus

ID | status  | dateChange 
1   | 1   | 01/01/2010 
2   | 1   | 01/01/2013 
3   | 1   | 01/01/2015 
3   | 2   | 01/01/2016 

,我想seletect以下數據

ID | Full name | Bith date | speciality | Date hired | Date fired 

結果必須是:

ID | Full name | Bith date | speciality | Date hired | Date fired 
1 | A A A  | 01/01/1980 | Manager | 01/01/2010 | null 
2 | B B B  | 01/01/1980 | Developer | 01/01/2013 | null 
3 | C C C  | 01/01/1980 | User  | 01/01/2015 | 01/01/2016 
3 | C C C  |01/01/1980 | User  | 01/01/2017 | null 

我的代碼:

SELECT Employees.id , Employees.fullName, Employees.birth, Employees.speciality, 
(SELECT dateChange FROM EmployeesStatus WHERE status=1 AND id=Employees.id) datehired, 
(SELECT dateChange FROM EmployeesStatus WHERE status=2 AND id=Employees.id) datefired FROM Employees 

HASE作爲導致以下消息:

消息512,級別16,狀態1,行1子查詢返回多個1個 值。這是當子查詢跟隨不允許=,!=,<,< =,

,> =,或當子查詢用作表達。

有什麼想法?

+0

那麼,如果返回多於1行,希望發生什麼?你只想要其中之一嗎?或者跳過子查詢,如果需要所有行,請執行左連接。 – jarlh

+0

我相信這個錯誤信息是不言自明的。當任何一個子查詢返回多個記錄時,您將收到此錯誤。你可以添加'LIMIT'來限制子查詢返回一條記錄,或者爲你的子查詢添加適當的過濾條件。 –

+1

我也建議不要在你的select語句中執行子查詢,它們通常性能很差。如果可以的話,嘗試將它們移入適當的連接。 –

回答

0

除了@scaisEdge答案:

SELECT 
    Employees.id, 
    Employees.fullName, 
    Employees.birth, 
    Employees.speciality 
    e1.dateChange as datehired, 
    MIN(e2.dateChange) as datefired 
FROM Employees 
INNER JOIN EmployeesStatus es1 on e1.status=1 AND e1.id=Employees.id 
LEFT JOIN EmployeesStatus es2 on e2.status=2 AND e2.id=Employees.id 
    AND e2.dateChange > e1.dateChange 
GROUP BY Employees.id, 
    Employees.fullName, 
    Employees.birth, 
    Employees.speciality, 
    e1.dateChange 
+1

,因爲它是未來的作品全名,出生,專業必須包括在小組by.but在這種情況下,我們只有一個(最大)僱用日期和一(最大) 。如果min,max和group被刪除,我們會得到最好的結果,直到現在結果爲:第一個日期僱傭的第一個日期被解僱,第一個僱傭的第二個日期被解僱,第二個僱傭的日期 - 第二個被解僱的日期。如果我們消除三個結果中的第二個,我們將會得到解決方案。 –

+0

@Po Lee,好的,編輯 – mnv

+1

謝謝,這很完美! –

0

嘗試以下操作:

SELECT E.ID,E.FULLNAME,E.BIRTH,E.SPECIALITY,ED.DATE_HIRED,ED.DATE_FIRED 
FROM EMPLOYEES E, 
(SELECT  ID, 
     MAX(CASE WHEN STATUS=1 THEN DATECHANGE ELSE NULL END)DATE_HIRED, 
     MAX(CASE WHEN STATUS=2 THEN DATECHANGE ELSE NULL END)DATE_FIRED 
FROM EMPLOYEESSTATUS 
GROUP BY ID)ED 
WHERE E.ID=ED.ID 

這個查詢會更快在性能方面,會給你同樣的結果。

+0

給出的查詢錯誤輸入 – Mansoor

+0

語法錯誤... – jarlh

+0

此代碼僅返回僱傭日期的最後一次。如果第一個最大值在min中改變,則返回第一個。 –

1

你應該使用一個連接,而不是=基於子查詢

SELECT 
    Employees.id 
    , Employees.fullName 
    , Employees.birth 
    , Employees.speciality 
    , e1.dateChange as datehired, e2.dateChange as datefired 
FROM Employees 
INNER JOIN EmployeesStatus es1 on e1.status=1 AND e1.id=Employees.id 
LEFT JOIN EmployeesStatus es2 on e2.status=2 AND e2.id=Employees.id 

或者你可以在條款中改用=在子查詢

+0

爲什麼不兩個左連接? – jarlh

+0

非常接近期望的結果,唯一的問題是,如果有兩個選擇,第二條線將在第一條發射場中有第一條發射,而不是零條紋 –

+0

如果有第二條發射日期,我們將獲得所有可能的組合2x2日期 –

0

試試這個

SELECT e.id , 
     e.fullName, 
     e.birth, 
     e.speciality, 
     CASE WHEN t1.status = 1 then max(t1.dateChange) else null end as "Date Hired", 
     CASE WHEN t2.status = 2 then max(t2.dateChange) else null end as "Date Fired", 
    FROM Employees e 
    LEFT JOIN EmployeesStatus t1 on t1.id = e.id and t1.status = 1 
    LEFT JOIN EmployeesStatus t2 on t2.id = e.id and t1.status = 2 

希望這個工程..