强制左连接仅从右表中匹配的Ids返回一行

时间:2017-08-09 10:53:14

标签: sql join sql-server-2012 left-join

我有两张表,我想加入,右表有时每个ID有一行以上。但我对所有的比赛都不感兴趣,只有第一个就足够了。

我该怎么做?

示例:

富:

     Id             FooColumns....
     100             xxxxxxxx
     200             xxxxxxxx
     300             xxxxxxxx
     400             xxxxxxxx

酒吧:

     Id             BarColumns....
     100             yyyyyyyy
     100             zzzzzzzz
     200             yyyyyyyy
     200             zzzzzzzz

我想要的是:

FooBar:

     Id             FooColumns....     BarColumns
     100             xxxxxxxx            yyyyyyyy
     200             xxxxxxxx            yyyyyyyy
     300             xxxxxxxx              nulls
     400             xxxxxxxx              nulls
Query: 
   Select F.*,B.* from Foo f left join Bar b on f.Id=B.Id   ?? 

4 个答案:

答案 0 :(得分:4)

一种方法使用row_number()

Select F.*, B.*
from Foo f left join
     (select b.*, row_number() over (partition by b.id order by id) as seqnum
      from bar b
     ) b
     on f.Id = B.Id and seqnum = 1; 

order by指定“第一个”的含义。 order by id是任意排序。

替代方法使用outer apply

Select F.*, B.*
from Foo f outer apply
     (select top 1 b.*
      from bar b
      where f.Id = B.Id
     ) b; 

在这种情况下,您可以在子查询中添加order by以根据某些列获取“第一个”。此外,这应该比以前的版本具有更好的性能。

答案 1 :(得分:2)

每次运行都会返回相同的行:

SELECT
  F.*,
  B.*
FROM Foo f
LEFT JOIN (SELECT
           Id,
           MIN(BarColumn)
           FROM bar
           GROUP BY id) b
ON f.Id = b.Id;

答案 2 :(得分:1)

在您的查询中添加LIMIT 1选项,这是一个示例:

Select C From T LIMIT 1.

这将只返回一行,如果您将订单更改为后代,也可以获取最后一项  示例:

SELECT C FROM T ORDER BY DESC LIMIT1

答案 3 :(得分:1)

获得所需结果集的另一种方法是使用FIRST_VALUE

Select F.*,B.* 
from Foo f 
left join (SELECT DISTINCT Id
         ,FIRST_VALUE(FooColumns) OVER(PARTITION BY Id ORDER BY id) AS FooColumns
           FROM bar)b on f.Id=B.Id;

<强> RextesterDemo