使用COMPUTE和COMPUTE BY进行SQL汇总查询

时间:2015-04-16 23:53:40

标签: sql-server-2012

我有一个包含两列(FileExtension和FileSize)的表,如下所示:

FileType FileSize
---------------------------
dll      129
bak      2323
ext      242424
ini      40
bak      532
log      32
bak      3253
dll      9094
bak      234
txt      587
dll      1000

我尝试编写SQL查询,可能使用ROLLUP或COMPUTE的组合,它将根据最大的FileSize提供FileTypes列中的前3个值。 Total列将包含在报告的底部,提供FileSize列中所有值的总和。查询结果如下:

FileType    FileExtension
-------------------------------
ext         242424
dll         10223
bak         6342
Total       259648

对于如何完成此查询的任何想法将不胜感激。谢谢!

2 个答案:

答案 0 :(得分:1)

这是基本的分组:

;with cte as (
select top 3 FileType, sum(FileSize) as FileExtension 
from TableName
group by FileType
order by FileExtension desc
)
select * from cte
union all
select 'Total', sum(FileExtension) from cte

如果我理解正确:

;with cte as (
    select top 3 FileType, sum(FileSize) as FileExtension 
    from TableName
    group by FileType
    order by FileExtension desc
    )
    select * from cte
    union all
    select 'Total', sum(FileSize) from TableName

答案 1 :(得分:1)

您可以在单个查询中获得每个FileSize的总FileType值和总计FileSize,如下所示:

SELECT
  FileType,
  TotalSize = SUM(FileSize)
FROM
  dbo.YourTable
GROUP BY
  ROLLUP(FileType)
;

作为ROLLUP分组功能的结果,您将有一个额外的行,TotalSize值是所有单个TotalSize值的总和,FileType设置为NULL。< / p>

要仅获得前三个总计和总计,您可以按TotalSize的降序对结果进行排序,并将TOP (4)添加到SELECT子句中:

SELECT TOP (4)
  FileType,
  TotalSize = SUM(FileSize)
FROM
  dbo.YourTable
GROUP BY
  ROLLUP(FileType)
ORDER BY
  TotalSize DESC
;

这几乎可以满足您的需求。您只需要将FileType替换为'Total',并将总计行移至结果集的末尾。

第一个问题很简单:只需使用COALESCE功能即可。要解决第二个问题,您可以将上述查询用作派生表并再次对结果进行排序,如下面的final query所示:

SELECT
  FileType = COALESCE(FileType, 'Total'),
  TotalSize
FROM
  (
    SELECT TOP (4)
      FileType,
      TotalSize = SUM(FileSize)
    FROM
      dbo.YourTable
    GROUP BY
      ROLLUP(FileType)
    ORDER BY
      TotalSize DESC
  ) AS s
ORDER BY
  CASE WHEN FileType IS NULL THEN 1 ELSE 0 END ASC,
  TotalSize DESC
;

外部查询的第一个排序标准是一个CASE表达式,对于总计行(基于其FileType为空的事实)的计算结果为1,并且对于每个其他计算结果为0。该结果的升序确保总行最终位于集合的底部。

请注意,如果FileType列具有自己的NULL,则如果NULL结果是前三个中的一个,则上述查询将无法正常工作。然后,您需要一种方法来区分来自源数据集的NULL和ROLLUP函数生成的NULL。您可以在此处使用GROUPING函数,

  

指示是否聚合GROUP BY列表中的指定列表达式。 GROUPING为聚合返回1,为结果集中的未聚合返回0。

因此,如果GROUPING(FileType)返回1,那将是累积行,否则它将是FileType小计。函数的结果可以很容易地用'Total'替换列值并对最终输出的结果进行排序。唯一的问题是,因为该函数仅在GROUP BY查询的直接上下文中有意义,但是对函数的结果进行排序将在稍后阶段执行,您可能需要将这些结果作为列返回派生表的供以后使用。以下rewrite of the previous query显示了具体方式:

SELECT
  FileType = CASE IsRollup WHEN 1 THEN 'Total' ELSE FileType END,
  TotalSize
FROM
  (
    SELECT TOP (4)
      FileType,
      TotalSize = SUM(FileSize),
      IsRollup  = GROUPING(FileType)
    FROM
      dbo.YourTable
    GROUP BY
      ROLLUP(FileType)
    ORDER BY
      TotalSize DESC
  ) AS s
ORDER BY
  IsRollup  ASC,
  TotalSize DESC
;