同一表中两列的总和

时间:2015-10-14 18:20:27

标签: sql-server union aggregate-functions data-partitioning

我正在查询数据仓库(因此我无法重新设计表格),我将尽力在一个简单的示例中模仿场景。

我们有3个主要的事件,更改和发布表。这3个通过称为中间的中间表连接。以下是它们的结构以及样本数据:

事件表:

enter image description here

更改表格

enter image description here

发布表:

enter image description here

中级表:

enter image description here

前3个表具有完全相同的结构,但中间表成对地保持这3个表的连接。例如,如果Rel1连接到Chg1,则中间表中的行为或。这两行没有区别,可能不会共存。

QUERY:

我想要所有发布记录以及相关事件的数量和相关更改的数量。以下是我实现这一目标的方法:

 WITH SourceTable AS(
SELECT R.ReleaseItem, R.Prop1, R.Prop2 , I.RelOrInc2 as [RelatedIncident] , Null as [RelatedChanges] FROM Release R
    LEFT JOIN [Intermediate] I
    ON R.ReleaseItem = I.RelOrInc1
    WHERE SUBSTRING(I.RelOrInc2,1,3) = 'Inc'
UNION

SELECT R.ReleaseItem, R.Prop1, R.Prop2 , I.RelOrInc1 , Null as [RelatedChanges] FROM Release R
    LEFT JOIN [Intermediate] I
    ON R.ReleaseItem = I.RelOrInc2
    WHERE SUBSTRING(I.RelOrInc1,1,3) = 'Inc'

UNION

SELECT R.ReleaseItem, R.Prop1, R.Prop2 , Null as [RelatedIncident] , I.RelOrInc2 as [RelatedChanges] FROM Release R
    LEFT JOIN [Intermediate] I
    ON R.ReleaseItem = I.RelOrInc1
    WHERE SUBSTRING(I.RelOrInc2,1,3) = 'Chg'
UNION

SELECT R.ReleaseItem, R.Prop1, R.Prop2 , Null as [RelatedIncident] , I.RelOrInc1  as [RelatedChanges] FROM Release R
    LEFT JOIN [Intermediate] I
    ON R.ReleaseItem = I.RelOrInc2
    WHERE SUBSTRING(I.RelOrInc1,1,3) = 'Chg'
    ) 

SELECT REL.* , COUNT(S.RelatedIncident) As [No Of Related Incidents] , COUNT(S.[RelatedChanges]) AS [No of Related Changes] FROM Release REL 
    LEFT JOIN SourceTable S
    ON REL.ReleaseItem = S.ReleaseItem
GROUP BY REL.ReleaseItem, REL.Prop1, REL.Prop2

此查询提供了我所需的结果:

enter image description here

但我认为我处理这个查询的方式是如此幼稚而且效率不高。我的数据仓库可能在中间表中包含大约数百万条记录,而我的方法可能太慢。

问题: 有没有更好的方法来获得更好的性能?

BTW,我正在使用MS SQL Server 2012

2 个答案:

答案 0 :(得分:2)

SELECT   
  R.ReleaseItem, R.Prop1, R.Prop2,
  [No Of Related Incidents] = (SELECT COUNT(*) FROM [Intermediate] i 
         WHERE (i.RelOrInc1 = r.ReleaseItem AND i.RelOrInc2 LIKE 'Inc%') 
         OR (i.RelOrInc2 = r.ReleaseItem AND i.RelOrInc1 LIKE 'Inc%')),
  [No of Related Changes] = (SELECT COUNT(*) FROM [Intermediate] i 
         WHERE (i.RelOrInc1 = r.ReleaseItem AND i.RelOrInc2 LIKE 'Chg%') 
         OR (i.RelOrInc2 = r.ReleaseItem AND i.RelOrInc1 LIKE 'Chg%'))
FROM Release R

答案 1 :(得分:1)

我认为这对你有用。对性能无能为力。你应该检查一下。

select r.releaseitem, 
       r.prop1,
       r.prop2,
       sum(case when t.relorinc2 like 'inc%' then 1 else 0 end) as incidents,
       sum(case when t.relorinc2 like 'chg%' then 1 else 0 end) as changes     
from (select relorinc1, relorinc2 from intermediate where relorinc1 like 'rel%'
      union all
      select relorinc2, relorinc1 from intermediate where relorinc2 like 'rel%')t
join release r on t.relorinc1 = r.releaseitem
group by r.releaseitem, r.prop1, r.prop2