T-SQL 带聚合的多层 CTE 查询
T-SQL Multi-layered CTE query with Aggregates
我有一个很长的通用 Table 表达式 (CTE) 查询,它试图计算每个用户的平均分数和组平均分数之间的百分比差异。
我希望我的多层 CTE 查询能够过滤大量记录并将其减少到以下 table:
UserID Tag UserAvg GroupAvg PercentDifference
1 Cat 72.50 73 -0.68
2 Cat 75.50 73 3.36
3 Cat 75 73 2.70
4 Cat 73.25 73 0.34
5 Cat 52.3333 73 -32.97
6 Cat 86.25 73 16.64
我的问题是获取 GroupAvg
列以便我可以执行 % Difference
计算。
说明我目前使用的方法;这是我的 CTE 查询的摘要:
WITH
-- select 1st 3 columns
UserScores AS (select UserID, Tag, Score FROM {multiple-table} WHERE Tag = 'Cat'),
-- add UserAvg column by grouping records
ScoreAverages AS (select UserID, Tag, AVG(Score) AS UserAvg GROUP BY UserID, Tag FROM UserScores),
-- calculate GroupAvg
GroupAverage AS (select AVG(UserAvg) AS GroupAvg FROM ScoreAverages),
-- calculate % difference
PercentDiff AS (select UserID, Tag, UserAvg, 73 AS GroupAvg, (((UserAvg-73)/((UserAvg+73)/2))*100) AS PercentDifference FROM ScoreAverages )
-- do something with results
select * from PercentDiff
足够简单;对吗?
请注意,我已将 73
硬编码为我的 GroupAvg
值。我不确定如何构建允许我从 ScoreAverages
到 PercentDiff
table.
所需的 sql 查询
是否可以在 SELECT 语句中执行 SELECT?我不是在寻找以下内容:
select * from X where Id in (select Id from Y where Name like '%abc%')
或者我只是想一次做太多?
是的,这叫做子select:
SELECT Column1, Column2, (SELECT QUERY THAT GETS GROUP AVERAGE) AS GroupAverage, Column3
FROM ...
要在另一列的计算中使用 sub-select 的结果,您可以重复 sub-select:
SELECT Column1, Column2, (SELECT QUERY THAT GETS GROUP AVERAGE) AS GroupAverage, (Column3 - (SELECT QUERY THAT GETS GROUP AVERAGE)) AS Column4
FROM ...
或者您可以像引用外部查询或后续 CTE 中的任何其他列一样引用它:
WITH CTE1 AS (SELECT Column1, Column2, (SELECT QUERY THAT GETS GROUP AVERAGE) AS GroupAverage
FROM ...)
, CTE2 AS (SELECT *, Column3-GroupAverage) AS Column4
FROM CTE1
JOIN ...
这是可能的,如 Tab Alleman 的回答所示,但在您的情况下则没有必要。由于您已经计算了 cte 链中的 GroupAvg
,因此您可以在最终查询中使用它。由于 GroupAverage
只包含一行,您可以简单地向其添加 CROSS JOIN:
;WITH
-- select 1st 3 columns
UserScores AS (
select UserID, Tag, Score
FROM {multiple-table}
WHERE Tag = 'Cat'),
-- add UserAvg column by grouping records
ScoreAverages AS (
select UserID, Tag, AVG(Score) AS UserAvg
FROM UserScores
GROUP BY UserID, Tag),
-- calculate GroupAvg
GroupAverage AS (
select AVG(UserAvg) AS GroupAvg
FROM ScoreAverages),
-- calculate % difference
PercentDiff AS (
select UserID, Tag, UserAvg, GroupAvg,
(((UserAvg-GroupAvg)/((UserAvg+GroupAvg)/2))*100) AS PercentDifference
FROM ScoreAverages
CROSS JOIN GroupAverage)
-- do something with results
select * from PercentDiff
我只是认为你可以像这样用一个 cte 来做到这一点。
;WITH UserAverages AS
(
SELECT UserID,
Tag,
AVG(Score) AS UserAvg,
AVG(AVG(Score)) OVER () AS GroupAvg
FROM {multiple-table}
WHERE Tag = 'Cat'
GROUP BY UserID, Tag
)
SELECT UserID,
Tag,
UserAvg,
GroupAvg,
(((UserAvg-GroupAvg)/((UserAvg+GroupAvg)/2))*100) AS PercentDifference
FROM UserAverages
我有一个很长的通用 Table 表达式 (CTE) 查询,它试图计算每个用户的平均分数和组平均分数之间的百分比差异。
我希望我的多层 CTE 查询能够过滤大量记录并将其减少到以下 table:
UserID Tag UserAvg GroupAvg PercentDifference
1 Cat 72.50 73 -0.68
2 Cat 75.50 73 3.36
3 Cat 75 73 2.70
4 Cat 73.25 73 0.34
5 Cat 52.3333 73 -32.97
6 Cat 86.25 73 16.64
我的问题是获取 GroupAvg
列以便我可以执行 % Difference
计算。
说明我目前使用的方法;这是我的 CTE 查询的摘要:
WITH
-- select 1st 3 columns
UserScores AS (select UserID, Tag, Score FROM {multiple-table} WHERE Tag = 'Cat'),
-- add UserAvg column by grouping records
ScoreAverages AS (select UserID, Tag, AVG(Score) AS UserAvg GROUP BY UserID, Tag FROM UserScores),
-- calculate GroupAvg
GroupAverage AS (select AVG(UserAvg) AS GroupAvg FROM ScoreAverages),
-- calculate % difference
PercentDiff AS (select UserID, Tag, UserAvg, 73 AS GroupAvg, (((UserAvg-73)/((UserAvg+73)/2))*100) AS PercentDifference FROM ScoreAverages )
-- do something with results
select * from PercentDiff
足够简单;对吗?
请注意,我已将 73
硬编码为我的 GroupAvg
值。我不确定如何构建允许我从 ScoreAverages
到 PercentDiff
table.
是否可以在 SELECT 语句中执行 SELECT?我不是在寻找以下内容:
select * from X where Id in (select Id from Y where Name like '%abc%')
或者我只是想一次做太多?
是的,这叫做子select:
SELECT Column1, Column2, (SELECT QUERY THAT GETS GROUP AVERAGE) AS GroupAverage, Column3
FROM ...
要在另一列的计算中使用 sub-select 的结果,您可以重复 sub-select:
SELECT Column1, Column2, (SELECT QUERY THAT GETS GROUP AVERAGE) AS GroupAverage, (Column3 - (SELECT QUERY THAT GETS GROUP AVERAGE)) AS Column4
FROM ...
或者您可以像引用外部查询或后续 CTE 中的任何其他列一样引用它:
WITH CTE1 AS (SELECT Column1, Column2, (SELECT QUERY THAT GETS GROUP AVERAGE) AS GroupAverage
FROM ...)
, CTE2 AS (SELECT *, Column3-GroupAverage) AS Column4
FROM CTE1
JOIN ...
这是可能的,如 Tab Alleman 的回答所示,但在您的情况下则没有必要。由于您已经计算了 cte 链中的 GroupAvg
,因此您可以在最终查询中使用它。由于 GroupAverage
只包含一行,您可以简单地向其添加 CROSS JOIN:
;WITH
-- select 1st 3 columns
UserScores AS (
select UserID, Tag, Score
FROM {multiple-table}
WHERE Tag = 'Cat'),
-- add UserAvg column by grouping records
ScoreAverages AS (
select UserID, Tag, AVG(Score) AS UserAvg
FROM UserScores
GROUP BY UserID, Tag),
-- calculate GroupAvg
GroupAverage AS (
select AVG(UserAvg) AS GroupAvg
FROM ScoreAverages),
-- calculate % difference
PercentDiff AS (
select UserID, Tag, UserAvg, GroupAvg,
(((UserAvg-GroupAvg)/((UserAvg+GroupAvg)/2))*100) AS PercentDifference
FROM ScoreAverages
CROSS JOIN GroupAverage)
-- do something with results
select * from PercentDiff
我只是认为你可以像这样用一个 cte 来做到这一点。
;WITH UserAverages AS
(
SELECT UserID,
Tag,
AVG(Score) AS UserAvg,
AVG(AVG(Score)) OVER () AS GroupAvg
FROM {multiple-table}
WHERE Tag = 'Cat'
GROUP BY UserID, Tag
)
SELECT UserID,
Tag,
UserAvg,
GroupAvg,
(((UserAvg-GroupAvg)/((UserAvg+GroupAvg)/2))*100) AS PercentDifference
FROM UserAverages