简体   繁体   English

获取查询结果总摘要行的最佳方法

[英]Best way to obtain total summary row of query result

I'm executing a query that gets a couple thousands rows as result, and the customer needs a row showing the sum totals of certain numeric columns. 我正在执行一个查询,该查询将获得数千行结果,而客户需要一行显示某些数字列的总和。 I've achieved this by using group by grouping sets, but this function supports up to 32 columns that are not in aggregate functions. 我通过使用分组分组来实现此目的,但是此功能最多支持32个不在聚合功能中的列。 My problem is that I have nearly 45 columns that I have to return, being only 10 that I leave out of the group by because of aggregate functions. 我的问题是我必须返回将近45列,由于聚合函数,我只剩下10列。

Original query was something like this: 原始查询如下所示:

    select
    o.Name, 
    ci.Id,
    ci.OriginId,
    ci.Varchar1,
    ci.Varchar2,
    ci.Varchar3,
    ci.Varchar4,
    ci.Varchar5,
    ci.Varchar6,
    ci.Varchar7,
    ci.Varchar8,
    ci.Varchar9,
    ci.Varchar10,
    ci.Varchar11,
    ci.Varchar12,
    ci.Varchar13,
    ci.Varchar14,
    ci.Varchar15,
    ci.Varchar16,
    ci.Varchar17,
    ci.Varchar18,
    ci.Varchar19,
    ci.Varchar20,       
    sum(ci.Decimal1) as Decimal1,
    sum(ci.Decimal1) as Decimal2,
    sum(ci.Decimal1) as Decimal3,
    sum(ci.Decimal1) as Decimal4,
    sum(ci.Decimal1) as Decimal5,
    sum(ci.Decimal1) as Decimal6,
    sum(ci.Decimal1) as Decimal7,
    sum(ci.Decimal1) as Decimal8,
    sum(ci.Decimal1) as Decimal9,
    sum(ci.Decimal1) as Decimal10,
    ci.Date1,
    ci.Date2,
    ci.Date3,
    ci.Date4,
    ci.Date5,
    ci.Date6,
    ci.Date7,
    ci.Date8,
    ci.Date9,
    ci.Date10

from 
    Items ci
    inner join Origins o 
    on ci.OriginId = o.Id 

group by grouping sets((
    o.Name,
    ci.Id,
    ci.OriginId,
    ci.Varchar1,
    ci.Varchar2,
    ci.Varchar3,
    ci.Varchar4,
    ci.Varchar5,
    ci.Varchar6,
    ci.Varchar7,
    ci.Varchar8,
    ci.Varchar9,
    ci.Varchar10,
    ci.Varchar11,
    ci.Varchar12,
    ci.Varchar13,
    ci.Varchar14,
    ci.Varchar15,
    ci.Varchar16,
    ci.Varchar17,
    ci.Varchar18,
    ci.Varchar19,
    ci.Varchar20,
    ci.Date1,
    ci.Date2,
    ci.Date3,
    ci.Date4,
    ci.Date5,
    ci.Date6,
    ci.Date7,
    ci.Date8,
    ci.Date9,
    ci.Date10), ())

I've tried to split the query in two, so that the amount of columns in the group by doesn't reach the maximum available. 我试图将查询一分为二,以使group by中的列数不达到可用的最大值。 If I execute each query separated I get the desired results, but if I union them I have an error (can't convert nvarchar to numeric). 如果我将每个查询分开执行,则会得到所需的结果,但是如果我将它们合并,则会出错(无法将nvarchar转换为数值)。

The result was something like this: 结果是这样的:

    select      
    o.name
    ci.Id,
    ci.OriginId,
    sum(ci.Decimal1) as Decimal1,
    sum(ci.Decimal1) as Decimal2,
    sum(ci.Decimal1) as Decimal3,
    sum(ci.Decimal1) as Decimal4,
    sum(ci.Decimal1) as Decimal5,
    sum(ci.Decimal1) as Decimal6,
    sum(ci.Decimal1) as Decimal7,
    sum(ci.Decimal1) as Decimal8,
    sum(ci.Decimal1) as Decimal9,
    sum(ci.Decimal1) as Decimal10,
    ci.Date1,
    ci.Date2,
    ci.Date3,
    ci.Date4,
    ci.Date5,
    ci.Date6,
    ci.Date7,
    ci.Date8,
    ci.Date9,
    ci.Date10

from 
    Items ci
    inner join Origins o 
    on ci.OriginId = o.Id 


group by grouping sets((
    o.Name,
    ci.Id,
    ci.OriginId,        
    ci.Date1,
    ci.Date2,
    ci.Date3,
    ci.Date4,
    ci.Date5,
    ci.Date6,
    ci.Date7,
    ci.Date8,
    ci.Date9,
    ci.Date10), ())

union

select  
    o.Name,
    ci.Id,
    ci.OriginId,
    ci.Varchar1,
    ci.Varchar2,
    ci.Varchar3,
    ci.Varchar4,
    ci.Varchar5,
    ci.Varchar6,
    ci.Varchar7,
    ci.Varchar8,
    ci.Varchar9,
    ci.Varchar10,
    ci.Varchar11,
    ci.Varchar12,
    ci.Varchar13,
    ci.Varchar14,
    ci.Varchar15,
    ci.Varchar16,
    ci.Varchar17,
    ci.Varchar18,
    ci.Varchar19,
    ci.Varchar20

from 
    Items ci
    inner join Origins o 
    on ci.OriginId = o.Id 

group by grouping sets((
    o.name,
    ci.Id,
    ci.OriginId,

    ci.Varchar1,
    ci.Varchar2,
    ci.Varchar3,
    ci.Varchar4,
    ci.Varchar5,
    ci.Varchar6,
    ci.Varchar7,
    ci.Varchar8,
    ci.Varchar9,
    ci.Varchar10,
    ci.Varchar11,
    ci.Varchar12,
    ci.Varchar13,
    ci.Varchar14,
    ci.Varchar15,
    ci.Varchar16,
    ci.Varchar17,
    ci.Varchar18,
    ci.Varchar19,
    ci.Varchar20), ())

Another way (if possible), would be to drop the group by grouping sets in SQL and generate a row with C#, since the result of the query is recieved by a IEnumerable, but I don't know if a SUM function is available. 另一种方法(如果可能的话)是通过对SQL中的集合进行分组来删除组并使用C#生成一行,因为查询的结果是由IEnumerable接收的,但是我不知道SUM函数是否可用。

Any advice will be appreciated. 任何建议将被认真考虑。

Thanks in advance. 提前致谢。

If what you are trying to do is basically all data plus total row, consider the following approach. 如果您要执行的操作基本上是所有数据加上总行,请考虑以下方法。 Do not group by grouping set that include all non-aggregated columns, instead group by row ID (existing one, which should be unique within all data rows, or artificial, created with row_number() function). 不要按包括所有未聚合列的分组集进行分组,而应按行ID分组(现有的ID在所有数据行中应该是唯一的,或者是用row_number()函数创建的人为的)。 Also consider joining auxiliary tables after total is calculated. 还应考虑在计算总计后加入辅助表。

The example follows. 示例如下。

Setup sample data: 设置样本数据:

declare @origs table (id int, name varchar(20));
insert into @origs values (1, 'orig1'), (2, 'orig2');

declare @items table (
    id int, orig_id int,
    column1 varchar(20), column2 varchar(20),
    value1 float, value2 float);

insert into @items values
(1, 1, 'c1.1', 'c2.1', 100, 10)
,(2, 1, 'c1.2', 'c2.2', 200, 20)
,(3, 2, 'c1.3', 'c2.3', 300, 30);

The query below returns all data plus total row the way you are trying to do it: 下面的查询以您尝试的方式返回所有数据和总行:

select i.id, o.name as orig, i.column1, i.column2, sum(i.value1) val1, sum(i.value2) val2
from @items i
    join @origs o on o.id = i.orig_id
group by grouping sets ((i.id, o.name, i.column1, i.column2), ());

The output is: 输出为:

id    orig  column1  column2  val1  val2
----- ----- -------- -------- ----- -----
1     orig1 c1.1     c2.1     100   10
2     orig1 c1.2     c2.2     200   20
3     orig2 c1.3     c2.3     300   30
NULL  NULL  NULL     NULL     600   60

Compare it to the next query, that groups data by a single column. 将其与下一个查询进行比较,该查询将数据按单个列进行分组。 Also auxiliary table @origs is joined after data is grouped. 分组数据后, @origs连接辅助表@origs

;with items as (
    select
        case grouping(id) when 0 then max(id) else NULL end id,
        case grouping(id) when 0 then max(orig_id) else NULL end orig_id,
        case grouping(id) when 0 then max(column1) else NULL end column1,
        case grouping(id) when 0 then max(column2) else NULL end column2,
        val1 = sum(value1),
        val2 = sum(value2)
    from @items
    group by rollup (id)
)
select i.id, o.name as orig, i.column1, i.column2, i.val1, i.val2
from items i
    left join @origs o on o.id = i.orig_id;

Output is the same : 输出是相同的

id    orig  column1  column2  val1  val2
----- ----- -------- -------- ----- -----
1     orig1 c1.1     c2.1     100   10
2     orig1 c1.2     c2.2     200   20
3     orig2 c1.3     c2.3     300   30
NULL  NULL  NULL     NULL     600   60

仅给出几千行,我将使用存储过程将没有总计的结果存储到临时表或表值变量中,然后将结果作为该表的UNION ALL加上顶部的总计返回它的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM