T-SQL 完整的外部联接语句不包括联接 table 中的唯一值
T-SQL Full Outer Join Statement not including unique values from joined table
我有一个 T-SQL 语句应该执行 Full OUTER JOIN
。
我会调用原始的select语句table1
,我会调用加入的tabletable2
.
我的查询没有返回在 table2
中唯一的值。更具体地说,它不会返回 table2 具有不在 table1 中的 segValue1 或 segValue2 的行。 (即它错误地表现得好像连接是 LEFT JOIN
而不是 FULL OUTER JOIN
)。
我不明白为什么要这样做。为什么这会表现得好像是左连接?
基本上发生的事情是,如果帐户没有 activity/does 不存在于实际值 table 中,那么它就不会被提取。
这里是 Table A、Table B、当前结果 Table 和期望结果 table:
的示例
Table Actual (SQL Server table with Actuals)
company segValue1 segValue2 ActualsAmount FiscalYear FiscalPeriod
NVV 5000 000 2017 12
NVV 6000 111 0 2017 12
NVV 8000 333 2017 12
NVV 4000 555 0 2017 12
Table Budget (SQL Server table with Budgets)
company segValue1 segValue2 BudgetAmt BalanceType FiscalYear FiscalPeriod
NVV 5000 000 D 2017 12
NVV 2000 111 D 2017 12
NVV 8000 444 D 2017 12
NVV 4000 555 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
NVV 6000 111 0 NULL
NVV 8000 333 NULL
NVV 8000 333 NULL
NVV 4000 555 0
Desired Result Table:
company segValue1 segValue2 ActualsAmount BudgetAmt
NVV 5000 000
NVV 6000 111 0 NULL
NVV 2000 111 NULL --<-correct
NVV 8000 444 NULL --<-correct
NVV 8000 333 NULL
NVV 4000 555 0
代码如下:
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
我怀疑这会破坏它
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);
我找到了一篇帮助我解决问题的文章。基本上我决定使用 Union All 并通过制作 "dummy" 列并将它们设置为零,然后在最后分组来解决 "same column name" 和 "equal number of columns" 联合特定要求问题。这个周末对我来说是一次巨大的学习经历。这个周末我了解了更多关于 tsql 的知识,然后我就把所有的时间都花在研究它上了。这是我发现这个 technique/structure "Better alternatives to outer joins" 的文章: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
我有一个 T-SQL 语句应该执行 Full OUTER JOIN
。
我会调用原始的select语句table1
,我会调用加入的tabletable2
.
我的查询没有返回在 table2
中唯一的值。更具体地说,它不会返回 table2 具有不在 table1 中的 segValue1 或 segValue2 的行。 (即它错误地表现得好像连接是 LEFT JOIN
而不是 FULL OUTER JOIN
)。
我不明白为什么要这样做。为什么这会表现得好像是左连接?
基本上发生的事情是,如果帐户没有 activity/does 不存在于实际值 table 中,那么它就不会被提取。
这里是 Table A、Table B、当前结果 Table 和期望结果 table:
的示例Table Actual (SQL Server table with Actuals)
company segValue1 segValue2 ActualsAmount FiscalYear FiscalPeriod
NVV 5000 000 2017 12
NVV 6000 111 0 2017 12
NVV 8000 333 2017 12
NVV 4000 555 0 2017 12
Table Budget (SQL Server table with Budgets)
company segValue1 segValue2 BudgetAmt BalanceType FiscalYear FiscalPeriod
NVV 5000 000 D 2017 12
NVV 2000 111 D 2017 12
NVV 8000 444 D 2017 12
NVV 4000 555 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
NVV 6000 111 0 NULL
NVV 8000 333 NULL
NVV 8000 333 NULL
NVV 4000 555 0
Desired Result Table:
company segValue1 segValue2 ActualsAmount BudgetAmt
NVV 5000 000
NVV 6000 111 0 NULL
NVV 2000 111 NULL --<-correct
NVV 8000 444 NULL --<-correct
NVV 8000 333 NULL
NVV 4000 555 0
代码如下:
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
我怀疑这会破坏它
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);
我找到了一篇帮助我解决问题的文章。基本上我决定使用 Union All 并通过制作 "dummy" 列并将它们设置为零,然后在最后分组来解决 "same column name" 和 "equal number of columns" 联合特定要求问题。这个周末对我来说是一次巨大的学习经历。这个周末我了解了更多关于 tsql 的知识,然后我就把所有的时间都花在研究它上了。这是我发现这个 technique/structure "Better alternatives to outer joins" 的文章: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