我有一个应该执行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
答案 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