2017-03-09 24 views
3

我有4個表EMPLOYEE,COMPANY,WORKSMANAGES。這些表的定義如下 -如何簡化where子句中的嵌套select?

CREATE TABLE EMPLOYEE 
(
EMPLOYEE_NAME VARCHAR2(50) NOT NULL PRIMARY KEY, 
STREET VARCHAR2(50) NOT NULL, 
CITY VARCHAR2(30) NOT NULL 
); 

CREATE TABLE COMPANY 
(
COMPANY_NAME VARCHAR2(100) NOT NULL PRIMARY KEY, 
CITY VARCHAR2(50) NOT NULL 
); 

CREATE TABLE WORKS 
(
EMPLOYEE_NAME VARCHAR2(50) NOT NULL PRIMARY KEY REFERENCES EMPLOYEE(EMPLOYEE_NAME), 
COMPANY_NAME VARCHAR2(100) NOT NULL REFERENCES COMPANY(COMPANY_NAME), 
SALARY NUMBER(12,2) NOT NULL 
); 

CREATE TABLE MANAGES 
(
EMPLOYEE_NAME VARCHAR2(50) NOT NULL PRIMARY KEY REFERENCES EMPLOYEE(EMPLOYEE_NAME), 
MANAGER_NAME VARCHAR2(50) NOT NULL 
); 

我需要找到所有與他們工作的公司居住在同一個城市的員工。 到目前爲止,我已經做到了這一點。

SELECT EMPLOYEE_NAME AS Names 
FROM EMPLOYEE 
WHERE CITY = (SELECT CITY 
       FROM COMPANY 
       WHERE (COMPANY_NAME = (SELECT COMPANY_NAME 
            FROM WORKS 
            WHERE WORKS.EMPLOYEE_NAME = EMPLOYEE.EMPLOYEE_NAME))); 

它工作正常。但我想知道有沒有更簡單的方法來做這個查詢?

+1

瞭解一個INNER JOIN是什麼,你會將它簡化爲大約一行SQL。你也應該重新考慮你的專欄。如果您有兩個名爲'John Smith'的員工或在同一城市有兩個辦事處的公司,會發生什麼情況? –

+0

@KenWhite感謝您的建議。我想我應該改變主鍵。 –

+0

我認爲你應該向ID號和公司添加ID列,然後你的WORKS表將是EMPLOYEE_ID,COM​​PANY_ID,你的MANAGES表將成爲EMPLOYEE_ID,MANAGER_ID,其中manager_id是EMPLOYEE_ID(一個工人不能由非 - 員工,對吧?)。 –

回答

2

你可以使用一個明確的內連接嵌套子查詢

SELECT EMPLOYEE.EMPLOYEE_NAME AS Names 
FROM EMPLOYEE 
INNER JOIN WORKS ON WORKS.EMPLOYEE_NAME = EMPLOYEE.EMPLOYEE_NAME 
INNER JOIN COMPANY ON EMPLOYEE.CITY = COMPANY.CITY 
+0

它給出了一個錯誤 - '00918。 00000 - 「不明確定義的列」 –

+0

更新了僱員的明確表名稱 – scaisEdge

+0

現在可以使用。謝謝。 :) –

1
select employee.employee_name 

    from company, employee, works 

    where company.company_name=works.company_name 

     and works.employee_name=employee.employee_name 
     and employee.city = company.city 
+1

呃。 WHERE子句連接是邪惡的。 :-) – DCookie

+1

雖然這段代碼可以解決這個問題,但[包括解釋](http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers)確實有助於提高質量您的帖子。請記住,您將來會爲讀者回答問題,而這些人可能不知道您的代碼建議的原因。 – DimaSan

+0

它工作正常。謝謝。 –

4
SELECT EMPLOYEE.EMPLOYEE_NAME As Names 
FROM EMPLOYEE 
INNER JOIN WORKS ON WORKS.EMPLOYEE_NAME = EMPLOYEE.EMPLOYEE_NAME 
INNER JOIN COMPANY ON COMPANY.COMPANY_NAME = WORKS.COMPANY_NAME 
WHERE COMPANY.CITY = EMPLOYEE.CITY 

實際上,這就是肯白用的是內部聯接暗示代替。

+0

你能解釋一下爲什麼'SELECT EMPLOYEE_NAME'給出錯誤 - ''列含糊定義''但是'SELECT EMPLOYEE.EMPLOYEE_NAME'很好用嗎? –

+0

EMPLOYEE_NAME存在於兩個表EMPLOYEE和WORKS中,所以當你只是說你想要EMPLOYEE_NAME字段時,SQL不知道你想從哪個表獲取數據。這就是爲什麼它含糊不清。所以你只需要在SELECT語句中指定表名和字段名。 – user3498540

2

你提到一個WHERE條款,所以你可以這樣做:

SELECT e.EMPLOYEE_NAME As Names 
FROM EMPLOYEE e 
WHERE e.CITY = (SELECT c.CITY 
       FROM Company c JOIN 
        Works w 
        ON c.COMPANY_NAME = w.COMPANY_NAME 
       WHERE w.EMPLOYEE_NAME = e.EMPLOYEE_NAME 
       ); 

注:

  • 這假定員工只爲一家公司工作。否則,子查詢可能會返回多行。您可以通過將=更改爲IN來處理這種情況。
  • 名稱是用於外鍵關係的非常糟糕的關鍵。通常數字ID更好。如果員工或公司更改名稱會發生​​什麼情況?
  • 表別名使查詢更容易編寫和閱讀。
+0

它工作正常。謝謝。但我想知道一件事。 Sid下面給出了一個答案,從多個表中選擇列並檢查where子句中的條件。這看起來更簡單。那麼,使用INNER JOIN還是兩者都有優勢? –

+0

Sid的答案對於已經過時約二十年的連接使用了古老的語法。在SQL中編寫'JOIN'的正確方法是使用明確的'JOIN'語法和'ON'子句。如果你想使用這種方法,那麼user3498540的解決方案是正確的選擇。 –

+0

好的。非常感謝。 :d –