2012-01-05 98 views
2

我連接3個表格並得到錯誤的結果。我們的目標是列出餐館表中的所有餐館,並顯示任何餐廳的評級,如果評級存在,則顯示空白,僅顯示漢堡評級。在SQL連接中需要幫助

這是SQL:

SELECT r.RestaurantID, RestaurantName, cr.Rating FROM Restaurant r 
     LEFT JOIN CustRating cr ON cr.RestaurantID = r.RestaurantID 
     LEFT JOIN FoodType ft ON ft.FoodTypeID = cr.FoodTypeID AND 
     ft.FoodTypeName = 'Burger' 

這是結果:

enter image description here

但是 '咖啡館C' 應該有等級= null,因爲我只想顯示伯格斯評分。什麼是適當的SQL?

的SQL語句來創建表和用數據填充:

CREATE TABLE [dbo].[Restaurant](
    [RestaurantID] [int] NOT NULL, 
    [RestaurantName] [varchar](250) NOT NULL 

) 

CREATE TABLE [dbo].[FoodType](
    [FoodTypeID] [int] NOT NULL, 
    [FoodTypeName] [varchar](50) NOT NULL 

) 
CREATE TABLE [dbo].[CustRating](
    [RestaurantID] [int] NOT NULL, 
    [FoodTypeID] [int] NOT NULL, 
    [Rating] [smallint] NOT NULL 
) 

BEGIN TRANSACTION; 
INSERT INTO [dbo].[CustRating]([RestaurantID], [FoodTypeID], [Rating]) 
SELECT 2, 1, 3 UNION ALL 
SELECT 3, 2, 2 
COMMIT; 
GO 

BEGIN TRANSACTION; 
INSERT INTO [dbo].[FoodType]([FoodTypeID], [FoodTypeName]) 
SELECT 1, N'Burger' UNION ALL 
SELECT 2, N'Taco' 
COMMIT; 
GO 

BEGIN TRANSACTION; 
INSERT INTO [dbo].[Restaurant]([RestaurantID], [RestaurantName]) 
SELECT 1, N'Cafe A' UNION ALL 
SELECT 2, N'Cafe B' UNION ALL 
SELECT 3, N'Cafe C' 
COMMIT; 
GO 
+0

+1 SQL DDL :)但您的SQL DML中的示例數據似乎不匹配您的圖片。 – onedaywhen 2012-01-05 08:45:10

+0

@onedaywhen我重新創建表並運行查詢,我得到相同的結果。也許你可以進一步解釋。 – 2012-01-05 16:58:06

回答

3
SELECT    
        Restaurant.* 
        ,CASE WHEN FoodType.FoodTypeID IS NULL THEN NULL ELSE CustRating.Rating END AS Rating 

FROM    Restaurant Restaurant 
LEFT OUTER JOIN CustRating CustRating 
ON     Restaurant.RestaurantID = CustRating.RestaurantID 
LEFT OUTER JOIN FoodType FoodType 
ON     FoodType.FoodTypeID = CustRating.FoodTypeID 
AND    FoodType.FoodTypeName = 'Burger' 
+0

+1做得好,如果不是複製master,當然8-) – 2012-01-05 08:41:21

2

嘗試:

SELECT r.RestaurantID, RestaurantName, T.Rating 
FROM Restaurant r 
    LEFT JOIN (
    select cr.RestaurantID, cr.Rating 
    from FoodType f 
    inner join CustRating cr on f.FoodTypeID = cr.FoodTypeID 
    where f.FoodTypeName = 'Burger' 
) T on r.RestaurantID = t.RestaurantID 
+0

+1爲正確答案,但查詢計劃涉及哈希連接 - 這是性能殺手,使用平面連接速度快4倍 – 2012-01-05 08:21:43

+0

@OlegDok:你能解釋哈希連接在哪裏嗎?我想它在子查詢結果(T)和餐館表之間? – 2012-01-05 08:28:04

+0

http://chat.stackoverflow.com/rooms/6415/query-plan – 2012-01-05 08:34:00

1

使用此查詢:

SELECT DISTINCT 
    r.RestaurantID, 
    RestaurantName, 
    CASE WHEN ft.FoodTypeID IS NULL THEN NULL ELSE cr.Rating END Rating 
FROM Restaurant r 
LEFT JOIN CustRating cr ON cr.RestaurantID = r.RestaurantID 
LEFT JOIN FoodType ft ON ft.FoodTypeID = cr.FoodTypeID AND 
ft.FoodTypeName = 'Burger' 
+0

注意表中缺少鍵(提示:你需要添加'DISTINCT'關鍵字:) – onedaywhen 2012-01-05 09:04:09

+0

@onedaywhen - yep,thanx! – 2012-01-05 09:15:48

-1

嘗試:

LEFT JOIN FoodType ft ON ft.FoodTypeID = cr.FoodTypeID WHERE 
    ft.FoodTypeID=1 

認爲可以幫助。

+0

錯!咖啡廳C簡直被拋出列表 – 2012-01-05 08:15:29

0

像這樣的東西應該工作;您需要刪除「TACO」 - 行前,實際上它

SELECT r.RestaurantID, RestaurantName, crft.Rating 
    FROM Restaurant r  
     LEFT JOIN (SELECT cr.RestaurantID, cr.Rating 
        FROM CustRating cr JOIN FoodType ft 
         ON ft.FoodTypeID = cr.FoodTypeID 
        WHERE ft.FoodTypeName = 'Burger') as crft 
     ON crft.RestaurantID = r.RestaurantID 

加入也許語法是不完全正確,因爲我沒有SQL服務器來測試它,但這個想法應該是這樣的,像這樣它的工作原理perfektly PostgreSQL的

SELECT "r"."RestaurantID", "RestaurantName", "crft"."Rating" 
    FROM "Restaurant" r  
     LEFT JOIN (SELECT * 
        FROM "CustRating" cr JOIN "FoodType" ft 
         ON "ft"."FoodTypeID" = "cr"."FoodTypeID" 
        WHERE "ft"."FoodTypeName" = 'Burger') as crft 
     ON "crft"."RestaurantID" = "r"."RestaurantID" 
+0

同樣的錯誤結果! – 2012-01-05 08:16:04

+0

你的權利!我有正確的解釋,但寫入SQL的速度很快......對不起,這個 – Hons 2012-01-05 08:30:43

+0

你跑了嗎?這是一個錯誤,不要寫得很快8-) – 2012-01-05 08:36:22

0

你有寫外部問題,所以在這裏加入是避免他們的另一種方法(和空值,外連接明確旨在返回:)

SELECT DISTINCT r.RestaurantID, r.RestaurantName, 
     N'Burger' AS FoodTypeName, cr.Rating 
    FROM dbo.Restaurant r 
     JOIN dbo.CustRating cr 
      ON r.RestaurantID = cr.RestaurantID 
     JOIN dbo.FoodType ft 
      ON ft.FoodTypeID = cr.FoodTypeID 
      AND ft.FoodTypeName = N'Burger' 
UNION 
SELECT DISTINCT r.RestaurantID, r.RestaurantName, 
     N'Burger' AS FoodTypeName, -1 AS Rating 
    FROM dbo.Restaurant r 
WHERE NOT EXISTS (
        SELECT * 
        FROM dbo.CustRating cr 
          JOIN dbo.FoodType ft 
          ON ft.FoodTypeID = cr.FoodTypeID 
           AND ft.FoodTypeName = N'Burger' 
        WHERE r.RestaurantID = cr.RestaurantID 
        );