【问题标题】:T-SQL Full Outer Join Statement not including unique values from joined tableT-SQL 完全外连接语句不包括连接表中的唯一值
【发布时间】:2018-07-06 11:13:36
【问题描述】:

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

我将调用原始选择语句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

【问题讨论】:

  • 我当然还没有见过“像棒球棒一样打我的脸”的东西!
  • 尝试将两个表都放入临时表,然后进行完全联接。
  • 任何反对外连接的地方都会排除行。 GLJ 在一家公司被过滤,APPY 在另一家公司被过滤
  • 无会计期间。我放弃。你没有实际测试过这个。
  • 查询仍然没有在发布的数据上运行。您在分解问题和编写问题陈述时遇到了问题。

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


【解决方案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);

【讨论】:

  • 我把它注释掉了,它仍然排除了 table2 中的唯一记录
  • 尝试用一个简单的数据示例重现。
  • 我简化了查询并添加了解释表。谢谢
  • @Paparazzi 考虑删除您的答案并发表评论
  • @Kermit 所以这是一个不正确的答案。评论是要求更多信息而不是回答。这显然不是信息请求。
【解决方案2】:

我找到了一篇帮助我弄清楚的文章。基本上,我决定使用 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

【讨论】:

    猜你喜欢
    • 2012-01-06
    • 1970-01-01
    • 1970-01-01
    • 2012-07-10
    • 2011-12-22
    • 1970-01-01
    • 2015-02-20
    • 2010-12-20
    相关资源
    最近更新 更多