多个表上的左外连接

J. *_*son 4 sql t-sql sql-server

我有以下sql语句:

    select  
    a.desc
   ,sum(bdd.amount)
   from t_main c 
   left outer join t_direct bds on (bds.repid=c.id) 
   left outer join tm_defination def a on (a.id =bds.sId)
   where c.repId=1000000134
   group by a.desc;
Run Code Online (Sandbox Code Playgroud)

当我运行它时,我得到以下结果:

   desc       amount
   NW         12.00
   SW         10
Run Code Online (Sandbox Code Playgroud)

当我尝试添加另一个左外连接以获取另一组值时:

   select  
    a.desc
   ,sum(bdd.amount)
   ,sum(i.amt)
   from t_main c 
   left outer join t_direct bds on (bds.repid=c.id) 
   left outer join tm_defination def a on (a.id =bdd.sId)
   left outer join t_ind i on (i.id=c.id)
   where c.repId=1000000134
   group by a.desc;
Run Code Online (Sandbox Code Playgroud)

它基本上使金额字段翻倍:

         desc    amount   amt
         NW       24.00   234.00
         SE       20.00   234.00
Run Code Online (Sandbox Code Playgroud)

虽然结果应该是:

        desc   amount   amt
        NW      12.00   234.00
        SE      10.00   NULL 
Run Code Online (Sandbox Code Playgroud)

我该如何解决?

小智 7

如果您确实需要按照提到的那样接收数据,则可以使用子查询来执行所需的计算.在这种情况下,您的代码可能如下所示:

select x.[desc], x.amount, y.amt
from
(
    select
         c.[desc]
       , sum (bdd.amount) as amount
       , c.id
    from t_main c 
    left outer join t_direct bds on (bds.repid=c.id) 
    left outer join tm_defination_def bdd on (bdd.id = bds.sId)
    where c.repId=1000000134
    group by c.id, c.[desc]
) x
left join
(
    select t.id, sum (t.amt) as amt 
    from t_ind t
    inner join t_main c
      on t.id = c.id
    where c.repID = 1000000134
    group by t.id
) y 
 on x.id = y.id
Run Code Online (Sandbox Code Playgroud)

在第一个子选择中,您将收到两个第一列的聚合数据:descamount根据需要进行分组.第二个选择将返回第一个集合中的amt每个id集合所需的值.这些结果之间的左连接将给出所需的结果.t_main由于性能问题,将表添加到第二个选择中.

另一种解决方案可以是:

select
     c.[desc]
   , sum (bdd.amount) as amount
   , amt = (select sum (amt) from t_ind where id = c.id)
from #t_main c 
left outer join t_direct bds on (bds.repid=c.id) 
left outer join tm_defination_def bdd on (bdd.id = bds.sId)
where c.repId = 1000000134
group by c.id, c.[desc]
Run Code Online (Sandbox Code Playgroud)

结果将是相同的.基本上,不是使用嵌套选择,而是对amt每个结果连接行内联执行求和的计算.在大表的情况下,第二解决方案的性能将比第一解决方案更差.


Mr *_*ose 6

由于最有可能存在多个关系,因此新的左外连接会强制在结果集中返回一些行.删除您的SUM并只查看返回的行并确切地确定您需要的行(如果适用,可以将其限制在特定类型的t_ind记录上),然后相应地调整您的查询.