2013-08-16 73 views
2

我有我的數據庫中的這些表:SQL子查詢的問題加入

旅遊 - 這是第一臺

Tourist_ID - primary key 
name...etc... 

EXTRA_CHARGES

Extra_Charge_ID - primary key 
Extra_Charge_Description 
Amount 

Tourist_Extra_Charges

Tourist_Extra_Charge_ID 
Extra_Charge_ID - foreign key 
Tourist_ID - foreign key 

因此,這裏的例子

我有一個旅遊與Tourist_ID - 86。這位身份證號碼爲86的遊客收取Extra_Charge_ID - 7和Extra_charge_ID - 11的額外費用;

我試着做一個查詢,所以我可以把EXTRA_CHARGES表中的遊客的名字和所有費用不是屬於這個遊客。

這裏是我嘗試的查詢 - 但它不會返回任何內容。

SELECT 
    Tourist.Name 
    , EXTRA_CHARGES.Extra_Charge_Description 
    , EXTRA_CHARGES.Amount 
FROM 
    Tourist 
    INNER JOIN TOURIST_EXTRA_CHARGES 
     ON Tourist.Tourist_ID = TOURIST_EXTRA_CHARGES.Tourist_ID 
    INNER JOIN EXTRA_CHARGES 
     ON TOURIST_EXTRA_CHARGES.Extra_Charge_ID = EXTRA_CHARGES.Extra_Charge_ID 
WHERE 
    Tourist.Tourist_ID= 86 
    and EXTRA_CHARGES.Extra_Charge_ID NOT IN 
    ( SELECT Extra_Charge_ID 
     FROM TOURIST_EXTRA_CHARGES te 
     WHERE te.Tourist_ID = 86 
    ) 

當然我能辦到的收費與此查詢

SELECT * FROM EXTRA_CHARGES e 
WHERE e.Extra_Charge_ID NOT IN 
(SELECT Extra_Charge_ID from TOURIST_EXTRA_CHARGES te 

    WHERE te.Tourist_ID = 86 
) 

,但我不能找到一個辦法讓這個旅遊名

+0

你能證明你的查詢的輸出給作爲更多的理解 – zxc

回答

1

您可以使用兩個選項,兩者幾乎相同,但根據您的DBMS不同而有所不同one may perform better than the other

兩者的原理是一樣的,獲得的旅遊及附加交叉聯接,所以你必須對所有遊客一切額外費用,然後使用NOT EXISTSLEFT JOIN/IS NULL消除一切額外費用,各旅遊有:

SELECT Tourist.Name, 
     EXTRA_CHARGES.Extra_Charge_Description, 
     EXTRA_CHARGES.Amount 
FROM Tourist 
     CROSS JOIN EXTRA_CHARGES 
WHERE Tourist.Tourist_ID= 86 
AND  NOT EXISTS 
     ( SELECT 1 
      FROM TOURIST_EXTRA_CHARGES 
      WHERE TOURIST_EXTRA_CHARGES.Tourist_ID = Tourist.Tourist_ID 
      AND  TOURIST_EXTRA_CHARGES.Extra_Charge_ID = EXTRA_CHARGES.Extra_Charge_ID 
     ); 


SELECT Tourist.Name, 
     EXTRA_CHARGES.Extra_Charge_Description, 
     EXTRA_CHARGES.Amount 
FROM Tourist 
     CROSS JOIN EXTRA_CHARGES 
     LEFT JOIN TOURIST_EXTRA_CHARGES 
      ON TOURIST_EXTRA_CHARGES.Tourist_ID = Tourist.Tourist_ID 
      AND TOURIST_EXTRA_CHARGES.Extra_Charge_ID = EXTRA_CHARGES.Extra_Charge_ID 
WHERE Tourist.Tourist_ID = 86 
AND  TOURIST_EXTRA_CHARGES.Tourist_Extra_Charge_ID IS NULL; 

編輯

因爲你所申請的兩個標準在邏輯上是不同的,你需要使用兩個查詢得到它。第一種是像以前一樣,額外的費用,一個遊客都沒有,第二個是誰擁有的一切額外費用遊客

SELECT Tourist.Name, 
     EXTRA_CHARGES.Extra_Charge_Description, 
     EXTRA_CHARGES.Amount 
FROM Tourist 
     CROSS JOIN EXTRA_CHARGES 
     LEFT JOIN TOURIST_EXTRA_CHARGES 
      ON TOURIST_EXTRA_CHARGES.Tourist_ID = Tourist.Tourist_ID 
      AND TOURIST_EXTRA_CHARGES.Extra_Charge_ID = EXTRA_CHARGES.Extra_Charge_ID 
WHERE Tourist.Tourist_ID = 1 
AND  TOURIST_EXTRA_CHARGES.Tourist_Extra_Charge_ID IS NULL 
UNION ALL 
SELECT Tourist.Name, 
     NULL, 
     NULL 
FROM Tourist 
     CROSS JOIN EXTRA_CHARGES 
     LEFT JOIN TOURIST_EXTRA_CHARGES 
      ON TOURIST_EXTRA_CHARGES.Tourist_ID = Tourist.Tourist_ID 
      AND TOURIST_EXTRA_CHARGES.Extra_Charge_ID = EXTRA_CHARGES.Extra_Charge_ID 
WHERE Tourist.Tourist_ID = 1 
GROUP BY Tourist.Name 
HAVING COUNT(*) = COUNT(TOURIST_EXTRA_CHARGES.Tourist_Extra_Charge_ID); 

Example on SQL Fiddle

+0

兩種方式都很完美 –

+0

在第一種情況下游客如何收取所有費用時如何處理 - 查詢將不返回任何行。但我需要這個名字 - 即使他們沒有額外收費 –

1

您可以包括旅遊名(對於Tourist_ID = 86),如SELECT語句的子查詢:

SELECT (SELECT Tourist.Name FROM Tourist WHERE Tourist_ID=86) TouristName, e.* 
FROM EXTRA_CHARGES e 
WHERE e.Extra_Charge_ID NOT IN 
     (SELECT Extra_Charge_ID 
     FROM TOURIST_EXTRA_CHARGES te 
     WHERE te.Tourist_ID = 86 
     ) 
+0

嘿它的工作原理,但是當我在列上得到名字 - 它寫成「沒有列名」。你知道如何得到它 –

+1

也許你已經省略了列名。寫像'(SELECT ....)AS TouristName' –

+0

是的,我太累了,我真的省略了:) Thans –

0

只需使用INNER JOIN ... ON .. <> ...

SELECT 
    Tourist.Name 
    , EXTRA_CHARGES.Extra_Charge_Description 
    , EXTRA_CHARGES.Amout 
FROM 
    Tourist 
    INNER JOIN TOURIST_EXTRA_CHARGES 
     ON Tourist.Tourist_ID <> TOURIST_EXTRA_CHARGES.Tourist_ID 
    INNER JOIN EXTRA_CHARGES 
     ON TOURIST_EXTRA_CHARGES.Extra_Charge_ID = EXTRA_CHARGES.Extra_Charge_ID 
WHERE 
    Tourist.Tourist_ID= 86 

在這裏看到: http://sqlfiddle.com/#!2/28665/2

1

你可以試試這個它的效率更高:

SELECT t.Name 
FROM Tourist t JOIN 
(SELECT * FROM EXTRA_CHARGES e 
JOIN TOURIST_EXTRA_CHARGE tec ON e.Extra_Charge_ID = tec.Extra_Charge_ID AND tec.TOURIST_EXTRA_CHARGES != 86) 
WHERE t.Tourist_ID = 86 

BTW。您不需要Tourist_Extra_Charges中的Tourist_Extra_Charge_ID列

+0

我以爲OP還需要EXTRA_CARGES列的結果。 –