Интересный запрос LEFT JOIN - PullRequest
1 голос
/ 12 августа 2010

ну интересно мне хотя бы ...

Скажем, у меня есть две таблицы:

myLookUpTable:

lookupId  | Name
--------    -----
1           Red
2           Green
3           Blue

и InfoTable:

infoId  lookupId  Amount  ParentId
------  --------  ------  --------
1       1         2       332
2       3         14      332

Как мне написать запрос, который возвращает каждую строку в myLookUpTable и включает связанную информацию из InfoTable, если она существует для определенного ParentId?

Пример:

запрос для parentId 221 вернет следующее для Name и Amount:

Name  Amount
----  ------
Red   
Green
Blue  

и запрос для parentId 332 вернет следующее для Name и Amount:

Name  Amount
----  ------
Red   2
Green 
Blue  14

Я попробовал около десяти вариантов левых соединений без удачи. Ниже мой последний:

SELECT mlut.Name, it.Amount
FROM   myLookUpTable as mlut
LEFT JOIN InfoTable as it
ON     mlut.lookupId = it.lookUpId OR it.ParentId is null
where  it.ParentId = 332

Это кажется простой проблемой, я просто что-то перебираю?

Ответы [ 6 ]

7 голосов
/ 12 августа 2010

Я думаю, что это будет делать то, что вы хотите.

SELECT mlut.Name, it.Amount 
  FROM myLookUpTable as mlut 
  LEFT JOIN InfoTable as it 
    ON mlut.lookupId = it.lookUpId 
   AND it.ParentId = 332 

Результаты тестирования SQL Server 2005 ниже

CREATE TABLE [dbo].[myLookUpTable](
    [lookupId] [int] NOT NULL,
    [Name] [varchar](10) NOT NULL
) ON [PRIMARY]

CREATE TABLE [dbo].[InfoTable](
    [infoId] [int] NOT NULL,
    [lookupId] [int] NOT NULL,
    [Amount] [int] NOT NULL,
    [ParentId] [int] NOT NULL
) ON [PRIMARY]

INSERT INTO myLookUpTable Values (1,'Red')
INSERT INTO myLookUpTable Values (2,'Green')
INSERT INTO myLookUpTable Values (3,'Blue')

INSERT INTO infoTable Values (1,1,2,332)
INSERT INTO infoTable Values (2,3,14,332)

SELECT mlut.Name, it.Amount  
  FROM myLookUpTable as mlut  
  LEFT JOIN InfoTable as it  
    ON mlut.lookupId = it.lookUpId  
   AND it.ParentId = 221

Red   NULL
Green NULL
Blue  NULL

SELECT mlut.Name, it.Amount  
  FROM myLookUpTable as mlut  
  LEFT JOIN InfoTable as it  
    ON mlut.lookupId = it.lookUpId  
   AND it.ParentId = 332

Red   2
Green NULL
Blue  14
1 голос
/ 12 августа 2010

OR it.ParentId is null часть не должна быть там.

В остальном - выглядит хорошо. Если у вас есть какие-то конкретные проблемы, пожалуйста, опишите их.

0 голосов
/ 12 августа 2010

Пост от Дейва Баркера - правильный ответ, НО: если вам всегда нужно возвращать точное число строк, соответствующее количеству строк в myLookUpTable, и (lookupid, ParentId) не является уникальным в InfoTable, который вы, возможно, захотитеиспользуйте одну из следующих опций:

-- sample contents - note that there are multiple amounts for lookupid, parentid (3,332)
INSERT INTO infoTable Values (1,1,2,332)
INSERT INTO infoTable Values (2,3,14,332)
INSERT INTO infoTable Values (3,3,24,332)
INSERT INTO infoTable Values (4,3,34,0)
INSERT INTO infoTable Values (5,3,44,332)

 -- option 1
    SELECT mlut.Name, it.Amount  
    FROM myLookUpTable as mlut  
        LEFT JOIN 
        (
            SELECT lookUpId, SUM(Amount) as Amount
            FROM InfoTable
            WHERE ParentId = 332
            GROUP BY lookupId
        ) as it  
        ON mlut.lookupId = it.lookUpId  

    -- option 2
    SELECT mlut.Name, it.Amount  
    FROM myLookUpTable as mlut  
        LEFT JOIN 
        (
            SELECT lookUpId, ParentId, SUM(Amount) as Amount
            FROM InfoTable
            GROUP BY lookupId, ParentId 
        ) as it  
        ON mlut.lookupId = it.lookUpId  
            AND it.ParentId = 332

    -- option 2 using CTE
    ;WITH it AS (
        SELECT lookUpId, ParentId, SUM(Amount) as Amount
        FROM InfoTable
        GROUP BY lookupId, ParentId 
    )
    SELECT mlut.Name, it.Amount  
    FROM myLookUpTable as mlut  
        LEFT JOIN it 
        ON mlut.lookupId = it.lookUpId  
        AND it.ParentId = 332

/*
Name       Amount
---------- -----------
Red        2
Green      NULL
Blue       82
*/
0 голосов
/ 12 августа 2010

Предложение WHERE для ParentID отменяет ваши усилия, чтобы СЛЕДУТЬ СОЕДИНЯТЬ все нулевые значения поиска. Вы можете переместить это ограничение в критерии LEFT JOIN:

SELECT mlut.Name, it.Amount
FROM   myLookUpTable as mlut
LEFT JOIN InfoTable as it
ON     mlut.lookupId = it.lookUpId AND it.ParentId = 332
0 голосов
/ 12 августа 2010

Вместо

where  it.ParentId = 332

вам нужно сделать

AND it.ParentId = 332

Также избавиться от OR it.ParentId is null

См. Также здесь MySQL - Какполучить NULL, если равенства не существует

0 голосов
/ 12 августа 2010

Проблема в этой строке:

where  it.ParentId = 332

Когда вы используете это условие условия, вы удаляете все строки, которые не имеют ParentId, например строки из таблицы слева, где справа нет соединяющих строк. Использование:

where it.ParentId IS NULL or it.ParentId = 332

избавиться от проверки IS NULL из оператора соединения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...