我有一个查询只返回在用户指定的时间范围内进行购买的位置,因此行数是可变的。然后,查询找到这些位置已经完成的所有类型的支出,并将其转动以创建动态数量的列。
所以我剩下的就是一张桌子,其中包含所有花费的位置以及他们花费的类别中的花费总和。
我现在想要做的是在顶部插入一个新行,该行是每个列的表中所有位置的平均值,但我不知道如何在可变数量的列中执行此操作行和列。
你们中的任何人都知道怎么做吗?我没有发布任何代码,因为它大约有90行,但如果这样会有所帮助,我可以。
提前致谢!
编辑:这是我的代码。我删除了尽可能多的无关代码(以及匿名表名),以便您可以简洁地看到我到目前为止所拥有的内容。
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX),
@RunForText varchar(max),
@Periods varchar(max)
Set @RunForText =
(
SELECT Distinct Stuff((Select ',' + c.Location
From Table..Table1 c For Xml Path ('')), 1, 1, '')) --GET UNIQUE LOCATIONS
Set @Periods = '201703' --SET TIME PERIOD FOR REPORT
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(vw.Description) --GET UNIQUE CATEGORIES OF SPEND AS COLUMNS
FROM Table..Table vw
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')
set @query = 'SELECT p.Number, ' + @cols + '
into ##tmp
from
(
SELECT
vw.Number,
vw.Name,
[Total] = vw.Total,
Description
FROM Table..Table vw
) p
pivot
(
SUM(p.Total)
for p.Description in (' + @cols + ')
) p '
execute sp_executesql @query;
SELECT * FROM ##tmp
目前,输出看起来像这样:
NUMBER | Category1 | Category2 | Category3
01 100.00 125.00 15.00
02 1.41 23.42 14.89
我想插入一行,以便表格如下所示:
NUMBER | Category1 | Category2 | Category3
Average 50.70 74.21 14.94
01 100.00 125.00 15.00
02 1.40 23.42 14.88
答案 0 :(得分:0)
您可以使用与创建数据透视查询的方法类似的方法,但通过调用Avg
来围绕列名称。根据您发布的代码,它看起来像:
declare @avgcols AS NVARCHAR(MAX)
select @avgcols =
STUFF((SELECT distinct ',avg(' + QUOTENAME(vw.Description) + ')'
FROM Table..Table vw
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')
set @query =
'INSERT into ##tmp (Number,' + @cols + ')
into ##tmp
Select ''Average'',' + @avgcols + ' FROM ##tmp'
execute sp_executesql @query;
答案 1 :(得分:0)
您当前方法的一大障碍是枢轴运营商。它一次只支持一个聚合函数(source - Microsoft Docs)。这意味着您无法合并总和,分钟,最大值和平均值。
这是有原因的。每列都有一个目的。但在您的示例中,Col1
有两个作业。有时它包含一个总和,有时是平均值。这是anti-pattern,我想避免。您不能在具有不一致内容的列之上构建。
当然,在您的情况下,您只是尝试添加总计/子总计行。不完全是犯罪!尽管如此,这种操作仍然最好在presentation layer中执行。一个很好的理由,往往更容易!
我的示例使用条件聚合(将group by clause与多个case expressions混合),而不是使用数据透视表。但结果是一样的。
在较高的层面上,基本方法是:
查询
/* Returns sample data with average sub total row.
*/
WITH SampleData AS
(
-- Conditional aggregation used instead of Pivot.
SELECT
Nu,
SUM(CASE WHEN Cat = 'C1' THEN Tot ELSE 0 END) AS C1,
SUM(CASE WHEN Cat = 'C2' THEN Tot ELSE 0 END) AS C2,
SUM(CASE WHEN Cat = 'C3' THEN Tot ELSE 0 END) AS C3
FROM
(
VALUES
(1, 'C1', 100.00),
(2, 'C1', 1.41),
(1, 'C2', 125.00),
(2, 'C2', 23.42),
(1, 'C3', 15.00),
(2, 'C3', 14.89)
) AS c(Nu, Cat, Tot)
GROUP BY
nu
)
-- Returns detail rows.
SELECT
*
FROM
SampleData
UNION ALL
-- Returns average row.
SELECT
'0' AS Nu,
AVG(C1) AS C1,
AVG(C2) AS C2,
AVG(C3) AS C3
FROM
SampleData
ORDER BY
Nu
;
返回
Nu C1 C2 C3
0 50.71 74.21 14.95
1 100.00 125.00 15.00
2 1.41 23.42 14.89
您还可以使用临时表和一些插入语句获得相同的结果。
如你所见。这是一个丑陋的问题,有很多事情要发生。将其转换为dynamic sql将不会很有趣。这就是为什么我建议你不要使用它。