使用Left join,Union和Right Join获得所需的结果

时间:2015-01-21 07:31:18

标签: sql ms-access ms-access-2007

我有两张桌子,即#34; CProduct"和" DProduct"。下面是例子:

CProduct:

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

DProduct:

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

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

5 个答案:

答案 0 :(得分:3)

应该只是一些子查询和完整的外连接。不确定为什么你认为需要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

答案 1 :(得分:1)

您正在使用与UNION相对的外连接以模仿FULL OUTER JOIN。这没关系,但是没有必要,因为SQL Server 2008(以及2005年也是如此)具有完整的外部联接。

然而,你的问题更为根本。您将加入CProduct和DProduct的所有记录,然后构建总和。因此,对于日期2014-01-01,CProduct中有两条记录,DProduct中有三条记录。你的连接给你六条记录(2x3)。然后你构建你的总和,从而将DProduct值分为两倍,将CProduct条目考虑为三倍。

说完这些之后,您不希望按日期将每个CProduct记录与每个DProduct记录一起加入。您想加入每个日期的总和。即首先聚合,然后加入。

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;

没有FULL OUTER JOIN:

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;

答案 2 :(得分:1)

这会得到你想要的结果 - 不太确定为什么其他的回答者认为加入和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

答案 3 :(得分:0)

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

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

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

答案 4 :(得分:0)

SELECT E121.EffectiveDate,suM(E12.Cfund)AS CFUND,AVG(e121.Dfund)AS EED1 EFT1 LEFT JOIN E12 ON E121.EffectiveDate = E12.EffectiveDate GROUP BY E121.EffectiveDate