【问题标题】:left outer join in t-sqlt-sql中的左外连接
【发布时间】:2012-12-09 05:50:27
【问题描述】:

我有以下两张表。我正在使用 SQL Server 2008 R2

Create table #tmp1 (
a char(1)
)

Create table #tmp2 (
id int,
a char(1),
val int
)

insert #tmp1 values ('A')
insert #tmp1 values ('B')
insert #tmp1 values ('C')

insert #tmp2 values (1,  'A', 10)
insert #tmp2 values (1,  'B', 20)
insert #tmp2 values (2,  'A', 30)
insert #tmp2 values (2,  'C', 40)

select * from #tmp1 t1 left outer join #tmp2 t2 on t1.a = t2.a
order by t2.id

这会返回结果集

A   1   A   10
B   1   B   20
C   2   C   40
A   2   A   30

我想要以下结果集

 A     1    A       10
 B     1    B       20
 C     1    null    null
 A     2    A       30
 B     2    null    null
 C     2    C       40

现在我通过创建一个像这样的交叉连接的新表然后进行外部连接来实现这一点

select * into #tmp3 from #tmp1 cross join (select distinct ID from #tmp2) t
select * from #tmp3 t1 left outer join #tmp2 t2 on t1.a = t2.a and t1.id = t2.id

有没有更好的方法来做到这一点?

谢谢

【问题讨论】:

  • 设置 SQL 很好。但是,您应该避免在查询中使用“*”,因为需要进行一些破译才能确定哪些列来自哪些表。

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


【解决方案1】:

要得到你想要的,你需要一个“驾驶”表。也就是说,您想要所有组合的完整列表,然后加入其他表以获取匹配项。这是一种方法:

select t1.a, t2.*
from (select t1.a as a, t2.id as id
      from (select distinct a from #tmp1 t1) t1
           cross join
           (select distinct id from #tmp2 t2) t2
     ) driving left outer join
     #tmp1 t1
     on t1.a = driving.a left outer join
     #tmp2 t2
     on t2.id = driving.id and
        t2.a = driving.a
order by t2.id

【讨论】:

  • 是的。我正在做与您正在做的事情相似的事情。我希望也许有一些新的 SQL 子句,如交叉应用、外部应用等,可以使代码更简单。
  • Gordon 说得对,您需要有一个“驾驶”表才能做到这一点。我们有与此非常相似的代码来完成同样的事情。让这种类型的查询工作起来并不简单。
【解决方案2】:

您要查找的是#tbl1 中的值和#tbl2 中id 列中的值的笛卡尔积。因为 #tbl2.id 中的值不是唯一的,所以为每个 #tbl2.id 值添加一个包含一行的附加表可能是更好的设计。然后你可以使用这个解决方案:

Create table #tmp1 (
a char(1)
)

Create table #tmp2 (
id int,
a char(1),
val int
)

Create table #tmp3 (
id int
)

insert #tmp1 values ('A')
insert #tmp1 values ('B')
insert #tmp1 values ('C')

insert #tmp3 values (1)
insert #tmp3 values (2)

insert #tmp2 values (1,  'A', 10)
insert #tmp2 values (1,  'B', 20)
insert #tmp2 values (2,  'A', 30)
insert #tmp2 values (2,  'C', 40)

SELECT  t3.id,t1.a,t2.val
FROM    #tmp1 AS t1
CROSS JOIN #tmp3 AS t3
LEFT OUTER JOIN #tmp2 AS t2
ON t1.a = t2.a AND t3.id = t2.id
ORDER BY t3.id, t1.a;

如果这不是一个选项,请改用这个:

SELECT  t3.id,t1.a,t2.val
FROM    #tmp1 AS t1
CROSS JOIN (SELECT DISTINCT id FROM #tmp2) AS t3
LEFT OUTER JOIN #tmp2 AS t2
ON t1.a = t2.a AND t3.id = t2.id
ORDER BY t3.id, t1.a;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-02
    • 1970-01-01
    • 2016-02-19
    相关资源
    最近更新 更多