2012-01-05 3 views
2

3 개의 테이블을 결합하여 잘못된 결과를 얻고 있습니다. 목표는 레스토랑 테이블에있는 모든 레스토랑을 나열하고 등급이있는 경우 레스토랑의 등급을 표시하는 것입니다. 그렇지 않으면 null을 표시하고 버거의 등급에 대해서만 표시합니다. 난 단지 표시 할 때문에 SQL 조인에 도움이 필요합니다.

enter image description here

그러나 '카페 C'는 평가 = 널 (null)이 있어야합니다
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' 

는 결과입니다

은 SQL입니다 Burgers에 대한 평가. 적절한 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 for SQL DDL :) 그러나 SQL DML의 샘플 데이터가 사용자의 그림과 일치하지 않는 것 같습니다. – onedaywhen

+0

@onedaywhen 테이블을 다시 만들고 쿼리를 실행하면 동일한 결과가 나타납니다. 어쩌면 당신은 더 설명 할 수 있습니다. –

답변

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 잘 완료, 물론 8-) –

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 배 더 빠릅니다 –

+0

@OlegDok : 해시 조인은 어디에서 설명 할 수 있습니까? 하위 쿼리 결과 (T)와 레스토랑 테이블 사이에 있다고 가정합니다. –

+0

http://chat.stackoverflow.com/rooms/6415/query-plan –

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

+0

@onedaywhen - yep, thanx! –

-1

시도 :

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

Think이 도움이 될 수 있습니다.

+0

틀렸어! 카페 C는 단순히리스트에서 빠져 나온다 –

0

다음과 같은 것이 좋습니다. 실제로

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-Server가 없기 때문에 아마 구문이 완전히 잘되지 않습니다 "TACO"-row을 제거해야하지만 아이디어는이를해야하고,이 같은 그것은

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

같은 잘못된 결과! –

+0

오른쪽! 나는 올바른 설명을했지만 SQL을 빨리 작성했습니다 ... 죄송합니다. – Hons

+0

실행 했습니까? 여기에 오류가있어서 빨리 쓰지 마라. 8-) –

0

그들을 피할 다른 방법 (명시 적 반환 :

설계 조인 외부 null 값이의 PostgreSQL을에 perfektly 작동3210
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 
        ); 
관련 문제