TSQL按部分聚合过滤

时间:2012-07-25 22:01:31

标签: sql sql-server tsql

SQL Server 2005 +。

我有一个包含以下架构/数据的表:

Name   Slots    Date
---------------------
Bob     1       1/1/2010 
Bob     2       1/8/2010 
Joe     4       1/2/2010 
Nat     1       1/4/2010 
Nat     3       1/3/2010 
Nat     8       1/9/2010 

我需要做的是找到一个特定名称的行,该行导致该名称的插槽总和达到或超过任意值 - 让我们说3。

所以在上面的例子中,Bob有两行。日期为1/8/2010的第二行将是我的匹配,因为1和2的总和= 3。

乔只有一行,他会匹配,因为4已经大于3。

Nat有3行,在他的情况下,匹配的行是第2行,日期为1/3/2010,因为1和3之和为4,而4大于3。

所以我的结果是:

Name   SlotsSum    Date
-------------------------
Bob     3       1/8/2010 
Joe     4       1/2/2010 
Nat     4       1/3/2010 

我知道我可以用光标做到这一点,但我希望采用基于集合的方法。

思想?

1 个答案:

答案 0 :(得分:2)

使用两种技术,我们可以做你想做的事。 CROSS APPLY计算一个运行总计,ROW_NUMBER以便我们可以选择超出限额的第一行。

declare @MyTable table (Name varchar(10), Slots int, Date date)
insert @MyTable values
('Bob',     1 ,      '1/1/2010'),
('Bob',     2 ,      '1/8/2010'), 
('Joe',     4 ,      '1/2/2010 '),
('Nat',     1 ,      '1/4/2010 '),
('Nat',     3 ,      '1/3/2010 '),
('Nat',     8 ,      '1/9/2010 ')

declare @Limit int = 3

;with cte as
(
    select Name, Slots, Date, RunningTotal,
    ROW_NUMBER() over (partition by Name order by Name, Date) as rn
    from @MyTable rsTable
    cross apply 
    (
        select SUM(Slots) as RunningTotal
        from @MyTable rsApply
        where Date <= rsTable.Date and Name = rsTable.Name
    ) rsRunningTotal
    where RunningTotal >= @Limit

)
select Name, RunningTotal, Date
from cte 
where rn = 1