SQL Server查询,鉴于运行总计,重设A列更改时(SQL Server Query, runn

2019-07-29 05:30发布

我的一位同事有哪些我想帮他一个问题。

他有包含以下数据(样本数据),在SQL视图: -

Category          Value
Cat A             10
Cat A             20
Cat A             30
Cat B             15
Cat B             15
Cat C             10
Cat C             10

他想将列添加到其保持的运行总计值列的视图。

此栏必须运行总复位类别发生变化时。

因此,输出数据必须是这样的: -

Category          Value       Running
Cat A             10          10
Cat A             20          30
Cat A             30          60
Cat B             15          15
Cat B             15          30
Cat C             10          10
Cat C             10          20

我们可以通过这样的加盟表到自身获得运行总计: -

select t1.id, t1.[count], SUM(t2.[count]) as sum
from TableA t1
inner join TableA t2 on t1.id >= t2.id
group by t1.id, t1.[count]
order by t1.id

问题是我们没有一个ID列,我们将如何指示运行总的类别发生变化时重新设置?

Answer 1:

这会不会对较大的表进行特别好,但会做的工作!

   select 'Cat A' as class,10 as value into #x
UNION ALL SELECT 'Cat A',20 
UNION ALL SELECT 'Cat A',30 
UNION ALL SELECT 'Cat B',15 
UNION ALL SELECT 'Cat B',15 
UNION ALL SELECT 'Cat C',10 
UNION ALL SELECT 'Cat C',10 

;WITH running_total AS
(
select *
,ROW_number() OVER (PARTITION BY class order by value ASC) as row 
from #x 
)
SELECT 
r1.class
,MAX(r1.value) as value
,SUM(r2.value) as running_total
FROM running_total r1
LEFT OUTER JOIN running_total r2 on r2.class = r1.class
                AND r2.row <= r1.row
GROUP BY 
r1.class
,r1.row

这是通过使用公用表表达式(CTE)和窗口功能。 的CTE工作在类似的方式,以一个子查询,其中,所述第一部分(称为running_total),增加了一个基于行的ID基于值的每个类。

ROW_NUMBER()可以作为记录在这里 ,但基本上它自动递增,这取决于你如何定义分区(基本上是一样的分组,但是不必组在主查询)和按类在建的顺序。

在这个例子中的类partitionign确保每个新的类别名称将具有最低值设置为1 - 如果你不是基于特定类别的总行驶总想你会删除该条款的这一部分。

CTE的第二部分选择从CTE的第一部分的结果,并加入到其自身上,其中类匹配。 通过加入上r2.row <= r1.row这确保了第二连接包括所有值<=当前行 - 在R1即行3包括行1,2,3中R2加入。



Answer 2:

您可以使用ROW_NUMBER()函数与联合OUTER APPLY

DECLARE @T TABLE (Category VARCHAR(5), Value INT)
INSERT INTO @T VALUES 
    ('Cat A', 10),
    ('Cat A', 20),
    ('Cat A', 30),
    ('Cat B', 15),
    ('Cat B', 15),
    ('Cat C', 10),
    ('Cat C', 10)

;WITH T AS
(   SELECT  Category, Value, ROW_NUMBER() OVER(PARTITION BY Category ORDER BY Value) [RowNumber]
    FROM    @T
)
SELECT  T1.Category,
        T1.Value,
        RunningTotal
FROM    T T1
        OUTER APPLY
        (   SELECT  SUM(Value) [RunningTotal]
            FROM    T T2
            WHERE   T2.Category = T1.Category
            AND     T2.RowNumber <= T1.RowNumber
        ) RunningTotal


文章来源: SQL Server Query, running total in view, reset when column A changes