具有不同 where 子句的多个聚合

Multiple aggregations with different where clauses

我有一个名为 Entries 的 table 管理特定单位的交易。

在条目中,有一个名为“销售来源”的列,用于指定已完成的销售类型。我正在尝试创建一个 table 来显示每种销售来源类型的单位收入总额。

例如:

一个名为 AB104 的单元有 8000 美元的收入,其中 5000 美元来自 Phone 来源,3000 美元来自传真来源。我想显示一个 table,在同一行中显示每种销售类型的单位编号和金额。

我尝试了以下查询:

SELECT Unit,
       sum(MoneyIN + MoneyOUT) AS Revenue,
       sum(VolumeOUT+ VolumeIN) AS volume,
       sum(WeightOUT + WeightIN)AS weight,
       PercentageR = convert(VARCHAR,convert(MONEY,sum(MoneyIN+MoneyOUT)*100 /
                                               (SELECT sum(MoneyIN + MoneyOUT)
                                                FROM Entries)), 1) + '%',
       PercentageV = convert(VARCHAR,convert(MONEY,sum(VolumeIN+VolumeOUT)*100 /
                                               (SELECT sum(VolumeIN + VolumeOUT)
                                                FROM Entries)), 1) + '%',
       PercentageW = convert(VARCHAR,convert(MONEY,sum(WeightIN+WeightOUT)*100 /
                                               (SELECT sum(WeightIN + WeightOUT)
                                                FROM Entries)), 1) + '%',
       LinkRevenue=
  (SELECT sum(MoneyIN+MoneyOUT)
   WHERE salesSource ='Link'),
       PhoneRevenue=
  (SELECT sum(MoneyIN+MoneyOUT)
   WHERE salesSource ='Phone'),
       EmailRevenue=
  (SELECT sum(MoneyIN+MoneyOUT)
   WHERE salesSource ='Email'),
       FaxRevenue=
  (SELECT sum(MoneyIN+MoneyOUT)
   WHERE salesSource ='Fax'),
       NoneRevenue=
  (SELECT sum(MoneyIN+MoneyOUT)
   WHERE salesSource ='None')
FROM Entries
GROUP BY Unit,
         SalesSource
ORDER BY Unit 

然而,该查询的问题在于它没有在一行中显示每个单位的不同收入类型。此查询将输出:

Unit | rev | vol | weight | % Revenue | % Weight | % Volume | $ Link |$Phone |$Email|$Fax |$None

AB104|5000$|22|15000| 17%| 10%|    15%| 0$|5000$|0$|0$|0$  

AB104|3000$|12|18000| 21%| 21%|    7%| 0$|0$|0$|3000$|0$

相反,我希望它将同一单元的所有详细信息分组在一行中,如下所示:

Unit | rev | vol | weight | % Revenue | % Weight | % Volume | $ Link |$Phone |$Email|$Fax |$None

AB104|8000$|34|33000| 38%| 31%|    22%| 0$|5000$|0$|3000$|0$  

我怎样才能做到这一点?当我从分组中取出 salesSource 时,出现错误。

您的分组依据有两列。您会看到每个 SalesSource 都有一个 Unit 行。可以单独将SalesSource加成一列看看。

此外,您希望避免在 select 子句中添加额外的 select,因为您需要对每个结果进行 SQL 运行 单独查询,在您的情况下每个结果 3 个查询。这将使您的查询不是很可扩展。

我认为您需要从分组子句和用例语句中删除 SalesSource。

 Sum(Case when SalesSource = 'Link' then (MoneyIn+MoneyOut) else 0 end) as LinkRevenue,

您可以使用常见的 table 表达式摆脱 select-in-a-select:

 ;with totals as (
      SELECT sum(WeightIN + WeightOUT) as WeightTotal,
             sum(VolumeIN + VolumeOUT) as VolumeTotal,
             sum(MoneyIN + MoneyOUT) as MoneyTotal
      FROM Entries
 )
 SELECT Unit,
   sum(MoneyIN + MoneyOUT) AS Revenue,
   sum(VolumeOUT+ VolumeIN) AS volume,
   sum(WeightOUT + WeightIN)AS weight,
   PercentageR = convert(VARCHAR,convert(MONEY,sum(MoneyIN+MoneyOUT)*100 /
                                           totals.MoneyTotal), 1) + '%',
   PercentageV = convert(VARCHAR,convert(MONEY,sum(VolumeIN+VolumeOUT)*100 /
                                           totals.VolumeTotal), 1) + '%',
   PercentageW = convert(VARCHAR,convert(MONEY,sum(WeightIN+WeightOUT)*100 /
                                           totals.WeightTotal), 1) + '%',
   Sum(Case when SalesSource = 'Link' then (MoneyIn+MoneyOut) else 0 end) as LinkRevenue,
 ....
 FROM Entries, totals
 GROUP BY Unit
 ORDER BY Unit 

你可以用更多的 cte 来清理它,我没有用 $ 符号格式化货币列,但你可以将它添加到最后的 select

With 
--create CTE with money columns summed for the pivotcte
TotalsCTEBySource (Unit, [Revenue],  SalesSource) AS
(SELECT Unit, MoneyIn+MoneyOut ,  SalesSource FROM Entries), 
--create CTE with table grand totals for % calcs
GrandTotalsCTE ([Revenue], [Volume],[Weight]) AS 
(SELECT sum(MoneyIn+MoneyOut) , sum(VolumeIn+VolumeOut) , sum(WeightIn+WeightOut) FROM Entries), 
--create totals by unit cte
TotalsCTEByUnit (Unit, [Revenue], [Volume],[Weight]) AS
(SELECT Unit, sum(MoneyIn+MoneyOut) , sum(VolumeIn+VolumeOut) , sum(WeightIn+WeightOut)
FROM Entries GROUP BY Unit), 
--create pivot cte to get the sales source values as column headers, use coalesce() to turn NULL into 0
PivotCTE (Unit, [$ Link],[$ Phone],[$ Fax],[$ Email],[$ None])AS
(   select Unit,coalesce(sum([Link]),0), coalesce(sum([Phone]),0),coalesce(sum([Fax]),0),
    coalesce(sum([Email]),0),coalesce(sum([None]),0) FROM(
    select Unit, [Link],[Phone],[Fax],[Email],[None] from TotalsCTEBySource
        PIVOT
            (sum(Revenue)FOR SalesSource in ([Link],[Phone],[Fax],[Email],[None])) pivottable 
    ) moneybygroup
group by Unit   )

--bring it all together
SELECT t.Unit, t.Revenue, t.Volume, t.Weight,
CONVERT(VARCHAR(50),round(t.Revenue/g.revenue*100,0))+' %' AS [% Revenue],
CONVERT(VARCHAR(50),round(t.Volume/g.Volume*100,0))+' %' AS [% Volume],
CONVERT(VARCHAR(50),round(t.Weight/g.Weight*100,0))+' %' AS [% Weight]
p.[$ Link],p.[$ Phone],p.[$ Fax],p.[$ Email],p.[$ None] 
FROM TotalsCTEByUnit t
Join PivotCTE p on t.unit=p.unit
join GrandTotalsCTE g on 1=1