T-SQL Full Outer Join语句不包括连接表中的唯一值

时间:2018-01-27 05:08:49

标签: sql-server tsql full-outer-join

我有一个应该执行Full OUTER JOIN的T-SQL语句。

我会调用原始的select语句table1,我将调用已连接的表table2

我的查询未返回table2中唯一的值。更具体地说,它不返回table2具有不在table1中的segValue1或segValue2的行。 (即,它错误地表现为加入是LEFT JOIN而不是FULL OUTER JOIN)。

我无法弄清楚为什么会这样做。为什么这会表现得好像是左连接?

基本上发生的事情是,如果帐户没有活动/在Actuals表中不存在,那么它就不会被接收。

以下是表A,表B,当前结果表和所需结果表的示例:

Table Actual (SQL Server table with Actuals)
company  segValue1  segValue2 ActualsAmount FiscalYear FiscalPeriod
NVV        5000        000        $20         2017         12
NVV        6000        111        $100        2017         12
NVV        8000        333        $40         2017         12
NVV        4000        555        $200        2017         12


Table Budget (SQL Server table with Budgets)
company  segValue1  segValue2  BudgetAmt BalanceType FiscalYear FiscalPeriod
NVV        5000        000        $10        D          2017        12
NVV        2000        111        $50        D          2017        12
NVV        8000        444        $90        D          2017        12
NVV        4000        555        $60        D          2017        12


Table that the current, erroneous Code is producing. 
Notice it is skipping records 2 and 3 from Table B because it is not in Table A:

company  segValue1  segValue2     ActualsAmount       BudgetAmt
NVV        5000        000              $20              $10                   
NVV        6000        111              $100             NULL                
NVV        8000        333              $40              NULL  
NVV        8000        333              $40              NULL              
NVV        4000        555              $200             $60   


Desired Result Table:
company  segValue1  segValue2     ActualsAmount       BudgetAmt
NVV        5000        000              $20              $10                   
NVV        6000        111              $100             NULL   
NVV        2000        111              NULL              $50       --<-correct            
NVV        8000        444              NULL              $90       --<-correct    
NVV        8000        333              $40              NULL                
NVV        4000        555              $200             $60  

以下是代码:

SELECT 
    A.Company, 
    A.segvalue1, A.segvalue2,      
    APYY.BalanceAmtBYTD, APYY.BalanceAmtBM, 
    SUM(CASE 
           WHEN FiscalPeriod BETWEEN '1' AND '12' AND FiscalYear = '2017' 
              THEN ActualsAmount 
              ELSE NULL 
        END) AS BalanceAmtCYTD, 
    SUM(CASE 
           WHEN FiscalPeriod = '12' AND FiscalYear = '2017' 
              THEN ActualsAmount
              ELSE NULL 
        END) AS BalanceAmtCYM
FROM 
    Actual  A

FULL OUTER JOIN

(SELECT 
         B.Company, B.segvalue1, B.segvalue2, 
         SUM(CASE WHEN FiscalPeriod BETWEEN '1' AND '12' AND FiscalYear = '2017' THEN BudgetAmt ELSE NULL END) as BalanceAmtBYTD, 
        SUM(CASE WHEN FiscalPeriod = '12' AND FiscalYear = '2017' THEN BudgetAmt ELSE NULL END) as BalanceAmtBM 
    FROM 
        Budget B 
    WHERE 
        FiscalYear = '2017' 
        AND BalanceType LIKE '%D%' 

    GROUP BY 
        B.Company, 
        B.segvalue1, B.segvalue2 ) APYY ON (A.Company = APYY.Company 
                                             AND A.segvalue1 = APYY.segvalue1 
                                             AND A.segvalue2 = APYY.segvalue2) 
WHERE 
    A.Company = 'NVV' 
GROUP BY 
    A.Company,  A.segvalue1,  A.segvalue2,
    APYY.BalanceAmtBYTD, APYY.BalanceAmtBM

2 个答案:

答案 0 :(得分:1)

我怀疑这是打破它

WHERE GLJ.Company = 'NVV' 

这不仅仅是答案,而是如何解决问题

declare @TableA table (Company varchar(5), segValue1 int, segValue2 int, ActualAmount int, FiscalYear int, FiscalPeriod int);
declare @TableB table (Company varchar(5), segValue1 int, segValue2 int, BudgetAmt int,    FiscalYear int, FiscalPeriod int);

insert into @TableA values 
             ('NVV', 5000, 000, 20, 2017, 12)
           , ('NVV', 6000, 111, 100, 2017, 12)
           , ('NVV', 8000, 333, 40, 2017, 12)
           , ('NVV', 4000, 555, 200, 2017, 12); 

insert into @TableB values 
             ('NVV', 5000, 000, 10, 2017, 12)
           , ('NVV', 2000, 111, 50, 2017, 12)
           , ('NVV', 8000, 444, 90, 2017, 12)
           , ('NVV', 4000, 555, 60, 2017, 12); 


select * from @TableA order by Company, segvalue1, segvalue2;

SELECT  B.Company, B.segvalue1, B.segvalue2, 
        SUM(CASE WHEN FiscalPeriod BETWEEN '1' AND '12' AND FiscalYear = '2017' THEN BudgetAmt ELSE NULL END) as BalanceAmtBYTD, 
        SUM(CASE WHEN FiscalPeriod = '12' AND FiscalYear = '2017' THEN BudgetAmt ELSE NULL END) as BalanceAmtBM 
FROM  @TableB B 
WHERE FiscalYear = '2017' 
GROUP BY B.Company, B.segvalue1, B.segvalue2 
ORDER BY B.Company, B.segvalue1, B.segvalue2; 

select isnull(A.Company, bb.Company) as Company, isnull(A.segvalue1, bb.segValue1) as segvalue1, isnull(A.segvalue2, bb.segValue2) as segvalue2, 
       bb.BalanceAmtBYTD, bb.BalanceAmtBM 
from @TableA a
full outer join ( SELECT  B.Company, B.segvalue1, B.segvalue2, 
                          SUM(CASE WHEN FiscalPeriod BETWEEN '1' AND '12' AND FiscalYear = '2017' THEN BudgetAmt ELSE NULL END) as BalanceAmtBYTD, 
                          SUM(CASE WHEN FiscalPeriod = '12' AND FiscalYear = '2017' THEN BudgetAmt ELSE NULL END) as BalanceAmtBM 
                    FROM  @TableB B 
                   WHERE  FiscalYear = '2017' 
                   GROUP BY  B.Company, B.segvalue1, B.segvalue2
                 ) bb
  on a.Company   = bb.Company
 and a.segValue1 = bb.segValue1
 and a.segValue2 = bb.segValue2
group by A.Company,   A.segvalue1,   A.segvalue2,  
         bb.Company,  bb.segvalue1,  bb.segvalue2,
         bb.BalanceAmtBYTD, bb.BalanceAmtBM 
order by isnull(A.Company, bb.Company), isnull(A.segvalue1, bb.segValue1), isnull(A.segvalue2, bb.segValue2);

答案 1 :(得分:0)

我发现了一篇帮助我弄明白的文章。基本上我决定使用Union All并通过制作“虚拟”列并将它们设置为零来解决“相同列名”和“相同列数”联合特定要求问题,然后在最后进行分组。这个周末对我来说是一次巨大的学习经历。这个周末我学到了更多关于tsql的知识,然后我全身心地研究它。这篇文章中我发现了这种技术/结构“外部连接的更好替代方案”:http://weblogs.sqlteam.com/jeffs/archive/2007/04/19/Full-Outer-Joins.aspx

这是我的最终T-SQL:

select 
Company,
segValue1,
segValue2,
segValue3,
segvalue4,


SUM(BalanceAmtCYTD) as BalanceAmtCYTD,
    SUM(BalanceAmtCYM) as BalanceAmtCYM,
    SUM(BalanceAmtAPYTD) as BalanceAmtAPYTD, 
    SUM(BalanceAmtBSPYBal) as BalanceAmtBSPYBal, 
    SUM(BalanceAmtBSCYBal) as BalanceAmtBSCYBal,
    SUM(BalanceAmtBSCYActivity) as BalanceAmtBSCYActivity,
    SUM(BalanceAmtBSCMActivity) as BalanceAmtBSCMActivity, 
    SUM(BalanceAmtAPYM) as BalanceAmtAPYM,
    SUM(BalanceAmtBYTD) as BalanceAmtBYTD,
    SUM(BalanceAmtBM) as BalanceAmtBM

From
(


Select
Company,
segValue1,
segValue2,
segValue3,
segvalue4,

SUM(CASE WHEN FiscalPeriod BETWEEN '1' AND '3' AND FiscalYear = '2018' THEN DebitAmount - CreditAmount END) as BalanceAmtCYTD, 
    SUM(CASE WHEN FiscalPeriod = '3' AND FiscalYear = '2018' THEN DebitAmount - CreditAmount  END) as BalanceAmtCYM, 
    SUM(CASE WHEN FiscalPeriod BETWEEN '1' AND '3' AND FiscalYear = '2017' THEN DebitAmount - CreditAmount  END) as BalanceAmtAPYTD, 
    SUM(CASE WHEN ((FiscalPeriod between '1' AND '3' AND FiscalYear = '2017') OR (FiscalYear < '2017')) THEN DebitAmount - CreditAmount  END) as BalanceAmtBSPYBal, 
    SUM(CASE WHEN ((FiscalPeriod between '1' AND '3' AND FiscalYear = '2018') OR (FiscalYear < '2018')) THEN DebitAmount - CreditAmount  END) as BalanceAmtBSCYBal, 
    SUM(CASE WHEN (FiscalPeriod between '1' AND '3') AND (FiscalYear = '2018') THEN DebitAmount - CreditAmount END) as BalanceAmtBSCYActivity, 
    SUM(CASE WHEN (FiscalPeriod = '3') AND (FiscalYear = '2018') THEN DebitAmount - CreditAmount END) as BalanceAmtBSCMActivity, 
    SUM(CASE WHEN (FiscalPeriod = '3') AND (FiscalYear = '2017') THEN DebitAmount - CreditAmount END) as BalanceAmtAPYM,
    0 as BalanceAmtBYTD,
    0 as BalanceAmtBM

    FROM GLJrnDtl
    where company = 'ovpca'
group by Company,
segValue1,
segValue2,
segValue3,
segvalue4

Union all

Select
Company,
segValue1,
segValue2,
segValue3,
segvalue4,

0 as BalanceAmtCYTD,
0 as BalanceAmtCYM,
0 as BalanceAmtAPYTD,
0 as BalanceAmtBSPYBal,
0 as BalanceAmtBSCYBal,
0 as BalanceAmtBSCYActivity, 
0 as BalanceAmtBSCMActivity,
0 as BalanceAmtAPYM,

SUM(CASE WHEN  FiscalPeriod BETWEEN '1' AND '3' AND FiscalYear = '2018' THEN BudgetAmt ELSE NULL END) as BalanceAmtBYTD, 
SUM(CASE WHEN FiscalPeriod = '3' AND FiscalYear = '2018' THEN BudgetAmt ELSE NULL END) as BalanceAmtBM


from GLBudgetDtl
where Company = 'ovpca' and balancetype = 'd'

group by Company,
segValue1,
segValue2,
segValue3,
segvalue4
) x

Group by
Company,
segValue1,
segValue2,
segValue3,
segvalue4