简体   繁体   English

如何合并汇总查询?

[英]How to union aggregated queries?

I have a query 我有一个查询

SELECT
    CntApp = COUNT(app.ApplicationID)
    ,r.RegionName
    ,d.DistrictName 
FROM dim.Application app
    JOIN dim.Geography g ON (app.ApplicationID  = g.GeographyID)   
       AND (app.CountryId = g.CountryId)
    JOIN dim.Region r   ON r.RegionID = g.RegionID  
    JOIN dim.District d ON d.DistrictId = g.DistrictID
    JOIN dim.ZIPcode z  ON g.ZIPcodeID = z.ZIPcodeID         
GROUP BY
    r.RegionName
    ,d.DistrictName

and

SELECT
    CntCon = COUNT(c.ContractID)
    ,r.RegionName
    ,d.DistrictName
FROM dim.Contract c  
    JOIN dim.Geography g ON (c.ContractID = g.GeographyID)   
       AND (c.CountryId = g.CountryId)
    JOIN dim.Region r   ON r.RegionID = g.RegionID  
    JOIN dim.District d ON d.DistrictId = g.DistrictID
    JOIN dim.ZIPcode z  ON g.ZIPcodeID = z.ZIPcodeID         
GROUP BY
    r.RegionName
    ,d.DistrictName

which I want to merge into one table, so the group by still works. 我想将其合并到一个表中,因此该分组依据仍然有效。 The result I want to get: 我想要得到的结果:

CntApp | CntCon | RegionName | DistrictName
31       24       Pardubicky   Pardubice
21       16       Pardubicky   Chrudim
...

I've tried UNION ALL but got something like this instead: 我已经尝试了UNION ALL,但是却得到了这样的东西:

CntApp | CntCon | RegionName | DistrictName
    NULL     24       Pardubicky   Pardubice
    21       NULL     Pardubicky   Pardubice
    26       NULL     Pardubicky   Chrudim
    ...

You need to join 2 subqueries. 您需要join 2个子查询。 This way you will get columns of both the queries side by side as you expect. 这样,您将按预期并排获得两个查询的列。

this should work : 这应该工作:

SELECT iq1.CntApp , iq2.CntCon, iq1.iq1.RegionName,iq1.DistrictName 
FROM
(
SELECT
    CntApp = COUNT(app.ApplicationID)
    ,r.RegionName
    ,d.DistrictName 
FROM dim.Application app
    JOIN dim.Geography g ON (app.ApplicationID  = g.GeographyID)   
       AND (app.CountryId = g.CountryId)
    JOIN dim.Region r   ON r.RegionID = g.RegionID  
    JOIN dim.District d ON d.DistrictId = g.DistrictID
    JOIN dim.ZIPcode z  ON g.ZIPcodeID = z.ZIPcodeID         
GROUP BY
    r.RegionName
    ,d.DistrictName
) iq1
inner join
(
SELECT
    CntCon = COUNT(c.ContractID)
    ,r.RegionName
    ,d.DistrictName
FROM dim.Contract c  
    JOIN dim.Geography g ON (c.ContractID = g.GeographyID)   
       AND (c.CountryId = g.CountryId)
    JOIN dim.Region r   ON r.RegionID = g.RegionID  
    JOIN dim.District d ON d.DistrictId = g.DistrictID
    JOIN dim.ZIPcode z  ON g.ZIPcodeID = z.ZIPcodeID         
GROUP BY
    r.RegionName
    ,d.DistrictName
) iq2
on
iq1.RegionName = iq2.iq1.RegionName 
and 
iq1.DistrictName = iq2.DistrictName 

UNION ALL will combine results column by column. UNION ALL将逐列合并结果。 You need to introduce fake columns and aggregate it again (or join like in the other solution): 您需要引入伪造的列并再次聚合(或像其他解决方案一样加入):

SELECT SUM(CntApp) CntApp, SUM(CntCon) CntCon, RegionName, DistrictName FROM (

    SELECT
        CntApp = COUNT(app.ApplicationID)
        ,CntCon = 0
        ,r.RegionName
        ,d.DistrictName 
    FROM dim.Application app
        JOIN dim.Geography g ON (app.ApplicationID  = g.GeographyID)   
           AND (app.CountryId = g.CountryId)
        JOIN dim.Region r   ON r.RegionID = g.RegionID  
        JOIN dim.District d ON d.DistrictId = g.DistrictID
        JOIN dim.ZIPcode z  ON g.ZIPcodeID = z.ZIPcodeID         
    GROUP BY
        r.RegionName
        ,d.DistrictName

    UNION ALL

    SELECT
        CntApp = 0
        ,CntCon = COUNT(c.ContractID)
        ,r.RegionName
        ,d.DistrictName
    FROM dim.Contract c  
        JOIN dim.Geography g ON (c.ContractID = g.GeographyID)   
           AND (c.CountryId = g.CountryId)
        JOIN dim.Region r   ON r.RegionID = g.RegionID  
        JOIN dim.District d ON d.DistrictId = g.DistrictID
        JOIN dim.ZIPcode z  ON g.ZIPcodeID = z.ZIPcodeID         
    GROUP BY
        r.RegionName
        ,d.DistrictName
) d
GROUP BY RegionName, DistrictName

You need a FULL JOIN 您需要FULL JOIN

SELECT coalesce(app.RegionName, c.RegionName) AS RegionName,
       coalesce(app.DistrictName, c.DistrictName) AS DistrictName,
      coalesce(app.CntApp,0) AS CntApp,
      coalesce(c.CntCon,0) AS CntCon
FROM 
    (SELECT
       CntApp = COUNT(app.ApplicationID)
       ,r.RegionName
       ,d.DistrictName 
    FROM dim.Application app
       JOIN dim.Geography g ON (app.ApplicationID  = g.GeographyID)   
         AND (app.CountryId = g.CountryId)
       JOIN dim.Region r   ON r.RegionID = g.RegionID  
       JOIN dim.District d ON d.DistrictId = g.DistrictID
       JOIN dim.ZIPcode z  ON g.ZIPcodeID = z.ZIPcodeID         
    GROUP BY
       r.RegionName
       ,d.DistrictName
    ) app
    FULL JOIN 
    (
       SELECT
       CntCon = COUNT(c.ContractID)
       ,r.RegionName
       ,d.DistrictName
    FROM dim.Contract c  
       JOIN dim.Geography g ON (c.ContractID = g.GeographyID)   
         AND (c.CountryId = g.CountryId)
       JOIN dim.Region r   ON r.RegionID = g.RegionID  
       JOIN dim.District d ON d.DistrictId = g.DistrictID
       JOIN dim.ZIPcode z  ON g.ZIPcodeID = z.ZIPcodeID         
    GROUP BY
       r.RegionName
       ,d.DistrictName
    ) c ON app.RegionName = c.RegionName AND app.DistrictName = c.DistrictName

You can probably ditch the union, and it will be safer because your results wont be affected by stray cartesian joins that might occur if bad data works its way into the g/r/d/z tables: 您可能可以放弃联合,这将更加安全,因为如果坏数据进入g / r / d / z表,则结果将不受杂散笛卡尔联接的影响:

SELECT
 CntApp,
 CntCon,
 r.RegionName,
 d.DistrictName 
FROM 
 dim.Geography g  
 INNER JOIN dim.Region r   ON r.RegionID = g.RegionID  
 INNER JOIN dim.District d ON d.DistrictId = g.DistrictID
 INNER JOIN dim.ZIPcode z  ON g.ZIPcodeID = z.ZIPcodeID 

 LEFT JOIN (SELECT ApplicationID, CountryID, COUNT(*) CntApp FROM dim.Application GROUP BY ApplicationID, CountryID) app
   ON (app.ApplicationID  = g.GeographyID) AND (app.CountryId = g.CountryId)

 LEFT JOIN (SELECT ContractID, CountryId, COUNT(*) as CntCon FROM dim.Contract GROUP BY ContractID, CountryId) c    
   ON (c.ContractID = g.GeographyID) AND (c.CountryId = g.CountryId)

Here's a bit of education point for you though: 不过,这里有一些教育要点:

If you have two blocks of data (from table, query, whatever) and you want to conenct them together vertically (more rows) then you use UNION If you want to conenct them together horizontally (more columns), you use JOIN 如果您有两个数据块(来自表,查询等),并且想要将它们垂直合并(更多行),则可以使用UNION。如果要水平将它们合并在一起(更多的列),则可以使用JOIN

If we have: 如果我们有:

a,b,c
a,b,c
a,b,c

And

a,y,z
a,y,z
a,y,z

This is what you get with UNION: 这是UNION的功能:

a,b,c
a,b,c
a,b,c
a,y,z
a,y,z
a,y,z

And this is what you get with JOIN: 这就是您通过JOIN得到的结果:

a,b,c,y,z
a,b,c,y,z
a,b,c,y,z

Remember this, is will serve you well 记住这一点,会很好地为您服务

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM