有趣的LEFT JOIN查询

时间:2010-08-11 23:49:44

标签: sql sql-server tsql sql-server-2008

至少对我来说很有趣......

说我有两张桌子:

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将返回NameAmount的以下内容:

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

并查询parentId 332将返回NameAmount的以下内容:

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 个答案:

答案 0 :(得分:7)

我认为这会做你想要的。

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 :(得分:1)

OR it.ParentId is null部分不应该存在。

否则 - 看起来不错。如果您遇到一些特殊问题,请说明一下。

答案 2 :(得分:0)

问题在于这一行:

where  it.ParentId = 332

当你在where where条件下使用它时,你将消除任何没有ParentId的行,例如左边没有连接行的表中的行。使用:

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

从连接语句中删除IS NULL检查。

答案 3 :(得分:0)

而不是

where  it.ParentId = 332

你需要做

AND it.ParentId = 332

还要摆脱OR it.ParentId is null

另见MySQL - How to get NULL if equality does not exist

答案 4 :(得分:0)

ParentID的WHERE子句用于撤消LEFT JOIN所有空查找值的工作。 您可以将该约束移动到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

答案 5 :(得分:0)

Dave Barker的帖子是正确答案但是: 如果您总是需要返回与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
*/