具有不同 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
我有一个名为 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