与AND的左连接仍在过滤行

时间:2014-07-04 09:45:24

标签: sql sql-server join

我有以下查询:

SELECT c.cardNo, acc.accountId
FROM card c
LEFT JOIN accounts acc ON c.accId = acc.id

上述查询返回500行。在上面的查询中,我正在检索所有卡片。我假装看到没有帐户的卡(仅作为示例)将返回NULL而不是accountId。

然后我想获得所有卡片,并且只获得在欧洲注册的国家/地区的帐户ID。所以我仍然想要500张卡,所以我尝试了以下内容:

SELECT c.cardNo, acc.accountId
FROM card c
LEFT JOIN accounts acc ON c.accId = acc.id AND acc.registrationContinent = 'EU'

然而令我惊讶的是,我得到300行(而不是500行),上面的内容也等同于我有一个WHERE子句。

有人可以解释为什么LEFT JOIN没有从卡表中返回所有记录吗?

3 个答案:

答案 0 :(得分:2)

因为您要过滤不属于“欧盟”的帐户。

如果你想在account.registrationContinent不是EU时在acc.accountid中使用NULL值,你可以

SELECT c.cardNo, 
case when acc.registrationContinent = 'EU' then acc.accountId else NULL end
FROM card c
LEFT JOIN accounts acc ON c.accId = acc.id

但我认为你有很多账户,有些是欧盟,有些没有欧盟。

因此,在第二次查询时,您仍然拥有所有卡片(我可以打赌您的卡片数量少于500张,可能少于300张卡片。)

如果第一个查询有多个帐户(每次使用不同的帐户),则第一个查询会多次返回同一张卡。

请检查

select count(*) from card

看看你有多少张不同的牌。

答案 1 :(得分:2)

您已在联接中指定了条件,现在这将是表格如何匹配在一起的一部分。要获得您想要的结果,您可以使用子查询来过滤您加入卡片的结果。像这样:

SELECT c.cardNo,
    acc.accountId
FROM card c
LEFT JOIN (
    SELECT accountId
    FROM accounts
    WHERE registrationContinent = 'EU'
    ) acc
    ON c.accId = acc.id

答案 2 :(得分:1)

如果在join语句中有条件,则会过滤第1个数据,然后发生Join。 在WHERE中给出条件时,首先连接发生,然后过滤数据。

以下案例可以帮助你......

DECLARE @A TABLE (ID INT, NAME VARCHAR(5), DEPID INT)
DECLARE @B TABLE (DEPID INT, DEPNAME VARCHAR(5),COUNTRY VARCHAR(5))
INSERT INTO @A VALUES (1,'JIT',101),(2,'PAT',101),(3,'JOM',101),(4,'MARK',102),(5,'FAL',103)
INSERT INTO @B VALUES (101,'HR','IND'),(102,'ACC','IND'),(103,'OPER','US')

SELECT      * FROM @A
SELECT      * FROM @B

<强>结果

enter image description here

SELECT      *
FROM        @A A 
LEFT JOIN   @B B ON A.DEPID = B.DEPID

SELECT      *
FROM        @A A 
LEFT JOIN   @B B ON A.DEPID = B.DEPID AND B.COUNTRY = 'US'

<强>结果

enter image description here