使用 Left join 、 Union 和 Right Join 得到想要的结果

Using Left join , Union and Right Join to get a desired result

我有两个表,即 "CProduct" 和 "DProduct"。下面是示例:

C产品:

EffectiveDate   CFund
2014-01-03      0.06
2014-01-03      0.12
2014-01-06      0.11

D产品:

EffectiveDate   DFund
2014-01-03      0.06
2014-01-06      0.12
2014-01-08      0.09

我想得到如下结果:

EffectiveDate  CFund   DFund
2014-01-03     0.18    0.06
2014-01-06     0.11    0.12
2014-01-08     NULL    0.09

我的查询是:

SELECT a.EffectiveDate,a.CFund,a.DFund      
FROM (
SELECT t1.EffectiveDate,Sum(t1.CFund) as CFund ,SUM(t2.DFund) as DFund FROM CProduct t1 
LEFT JOIN DProduct t2 ON t1.EffectiveDate = t2.EffectiveDate Group By t1.EffectiveDate
UNION
SELECT t1.EffectiveDate,SUM(t2.CFund) as CFund ,Sum(t1.DFund) as DFund FROM DProduct t1 
LEFT JOIN CProduct t2 ON t1.EffectiveDate = t2.EffectiveDate Group By t1.EffectiveDate
) a

但我没有得到想要的结果。

应该只是一些子查询和一个完整的外部连接。不确定为什么您认为 UNION 是必需的(特别是因为它消除了重复行):

SELECT
    COALESCE(t1.EffectiveDate,t2.EffectiveDate) as EffectiveDate,
    t1.Total,
    t2.Total
FROM
    (select EffectiveDate,SUM(CFund)
    from CProduct
    group by EffectiveDate) as t1(EffectiveDate,Total)
        full outer join
    (select EffectiveDate,SUM(DFund)
    from DProduct
    group by EffectiveDate) as t2(EffectiveDate,Total)
        on
            t1.EffectiveDate = t2.EffectiveDate

您正在使用 UNION 的反向外连接来模仿 FULL OUTER JOIN。这没关系,但不是必需的,因为 SQL Server 2008(和 2005,就此而言)具有完整的外部联接。

然而,你的问题更为根本。您正在连接来自 CProduct 和 DProduct 的所有记录,然后构建总和。所以说日期 2014-01-01 在 CProduct 中有两条记录,在 DProduct 中有三条记录。您的加入为您提供了六个记录 (2x3)。然后你建立你的总和,因此考虑 DProduct 值的两倍和 CProduct 条目的三倍。

话虽如此,您不想按日期将每个 CProduct 记录与每个 DProduct 记录连接起来。您想要加入每个日期的总和。 IE。先聚合,后加入。

select 
  coalesce(c.effectivedate, d.effectivedate) as effectivedate,
  coalesce(c.sumfund,0) as cfund, 
  coalesce(d.sumfund,0) as dfund
from 
  (select effectivedate, sum(cfund) as sumfund from cproduct group by effectivedate) c
full outer join 
  (select effectivedate, sum(dfund) as sumfund from dproduct group by effectivedate) d
on c.effectivedate = d.effectivedate;

没有完全外部连接:

select 
  c.effectivedate,
  c.sumfund as cfund, 
  d.sumfund as dfund
from 
  (select effectivedate, sum(cfund) as sumfund from cproduct group by effectivedate) c
left outer join 
  (select effectivedate, sum(dfund) as sumfund from dproduct group by effectivedate) d
on c.effectivedate = d.effectivedate
union
select 
  d.effectivedate,
  c.sumfund as cfund, 
  d.sumfund as dfund
from 
  (select effectivedate, sum(cfund) as sumfund from cproduct group by effectivedate) c
right outer join 
  (select effectivedate, sum(dfund) as sumfund from dproduct group by effectivedate) d
on c.effectivedate = d.effectivedate;

使用合并或类似方法是正确的解决方案。

但是在您的情况下,可以避免它,我们的想法是在单独的子查询中获取日期,然后通过左连接获得总和。

SELECT
Date.EffectiveDate as EffectiveDate,
t1.Total as t1,
t2.Total as t2
FROM
(select distinct EffectiveDate from CProduct
 union
 select distinct EffectiveDate from DProduct
) as Date
left join
(select EffectiveDate,SUM(CFund)
from CProduct
group by EffectiveDate) as t1(EffectiveDate,Total)
on Date.EffectiveDate=t1.EffectiveDate
left join
(select EffectiveDate,SUM(DFund)
from DProduct
group by EffectiveDate) as t2(EffectiveDate,Total)
    on
        Date.EffectiveDate = t2.EffectiveDate

SELECT E121.EffectiveDate,suM(E12.Cfund) AS CFUND,AVG(e121.Dfund) AS DFUND FROM E121 LEFT JOIN E12 ON E121.EffectiveDate=E12.EffectiveDate 分组 E121.EffectiveDate

这得到了您想要的结果 - 不太清楚为什么其他回答者认为加入和 COALESCE 如此重要:

SELECT a.EffectiveDate, SUM(a.CFund) AS CFund, SUM(a.DFund) AS DFund
FROM (
    SELECT c.EffectiveDate, c.CFund, NULL AS DFund
    FROM CProduct c
    UNION ALL
    SELECT d.EffectiveDate, NULL AS CFund, d.DFund
    FROM DProduct d
) a
GROUP BY a.EffectiveDate
ORDER BY a.EffectiveDate

在 SQL Fiddle 中,针对 SQLite(我没有检查过,但应该也可以使用 Access):http://sqlfiddle.com/#!7/80158/1