Sql 使用左连接、并集和右连接获得所需结果

Sql 使用左连接、并集和右连接获得所需结果,sql,ms-access,ms-access-2007,Sql,Ms Access,Ms Access 2007,我有两个表格,即“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

我有两个表格,即“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

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

应该只是一些子查询和一个完整的外部联接。不确定您为什么认为需要
联合(特别是因为这样可以消除重复行):


应该只是一些子查询和一个完整的外部联接。不确定您为什么认为需要
联合(特别是因为这样可以消除重复行):


为了模拟完全的外部联接,您正在使用带有并集的反向外部联接。这是可以的,但不是必需的,因为SQLServer2008(以及2005)具有完整的外部联接

然而,你的问题更为根本。您将合并来自CProduct和DProduct的所有记录,然后生成总和。因此,假设2014年1月1日,CProduct中有两条记录,DProduct中有三条记录。您的加入将为您提供六条记录(2x3)。然后构建总和,从而将D产品值考虑两倍,将C产品条目考虑三倍

话虽如此,您不希望按日期将每个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;
没有完全外部连接:

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;

为了模拟完全的外部联接,您正在使用带有并集的反向外部联接。这是可以的,但不是必需的,因为SQLServer2008(以及2005)具有完整的外部联接

然而,你的问题更为根本。您将合并来自CProduct和DProduct的所有记录,然后生成总和。因此,假设2014年1月1日,CProduct中有两条记录,DProduct中有三条记录。您的加入将为您提供六条记录(2x3)。然后构建总和,从而将D产品值考虑两倍,将C产品条目考虑三倍

话虽如此,您不希望按日期将每个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;
没有完全外部连接:

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
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

选择E121.EffectiveDate,suM(E12.Cfund)作为Cfund,AVG(E121.Dfund)作为Dfund从E121左侧加入E121上的E12.EffectiveDate=E12.EffectiveDate按E121.EffectiveDate分组选择E121.EffectiveDate,suM(E12.Cfund)作为Cfund,AVG(E121.Dfund)从E121左到E121上的E12。EffectiveDate=E12。EffectiveDate按E121分组。EffectiveDate

这会得到您想要的结果-不太清楚为什么其他回答者认为连接和
合并如此重要:

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):

这会得到您想要的结果-不太清楚为什么其他回答者认为连接和联合是如此重要:

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):

有没有不使用合并函数的方法???@vivek为什么要避免合并?@Taemyr,因为我需要与vba(MS-Access)一起使用它这是一个sql函数,在vba中不起作用。@vivek-一个问题最多允许有5个标记,而您只使用了3个,但您认为应用2个SQL Server标记比包含更重要?@vivek有没有不使用合并功能的方法???@vivek为什么要避免合并?@Taemyr,因为我需要将其与vba(MS-ACCESS)一起使用这是一个sql函数,在vba中不起作用。@vivek-一个问题最多允许有5个标记,而您只使用了3个,但您认为应用2个sql Server标记比包含两个问题更重要?@vivek两个问题:1。D产品中是否有重复的日期?2.CProduct中是否有日期在DProduct中不存在?@ZThrosten是的,两个条件都可能存在。两个问题:1。D产品中是否有重复的日期?2.CProduct中是否有日期在DProduct中不存在?@ZThrosten是的,这两个条件都可能存在。当不存在日期条目时,OP请求NULL,因此最后两个合并函数是unecesarry。@Thorsten即使在将coalesce替换为Nz之后,您能否提供与上述查询相同的工作vba查询,它在vba的From子句中给出语法错误。不知道为什么。但是在sql中工作得很好。@vivek:VBA?微软接入?您已将您的请求标记为SQL Server 2008。我认为MS Access不支持完全外部联接,因此我添加了一个模拟查询(尽管我认为您应该能够使用所提供的信息自己构建此查询)。@Thorsten是的,这是我的错误。我为此道歉。我已经改正了。我现在正在尝试。@ThorstenKettner我不太确定“左外连接”是否适用于vba。当日期不存在任何条目时,OP请求NULL,因此最后两个合并函数是unecesarry。@Thorsten您能否提供与上述查询相同的工作vba查询,即使将coalesce替换为Nz,它在vba的From子句中给出语法错误。不知道为什么。但是在sql中工作得很好。@vivek:VBA?微软接入?您已将您的请求标记为SQL Server 2008。我认为MS Access不支持完全外部联接,因此我添加了一个模拟查询(尽管我认为您应该能够使用所提供的信息自己构建此查询)。@Thorsten是的,这是我的错误。我为此道歉。我已经改正了。我现在正在尝试。@ThorstenKettner我不太确定“左外连接”是否适用于vba。能否请您提供等效的工作vba qu