根据给定条件汇总记录

Summing up the records as per given conditions

我有一个如下所示的 table,我需要的是针对任何特定基金和截至任何特定日期的逻辑将对金额值求和。假设我需要 3 个日期的总和,分别是 01/28/2015、03/30/2015 和 04/01/2015。然后逻辑将检查第一个日期 table 中有多少条记录。如果它找到了不止一条记录,那么它将对 amount 值求和。然后对于下一个日期,它将汇总到下一个日期,但从上一个日期开始汇总。

Id Fund   Date         Amount
1   A   01/20/2015      250
2   A   02/28/2015      300
3   A   03/20/2015      400
4   A   03/30/2015      200
5   B   04/01/2015      500
6   B   04/01/2015      600

我希望结果如下所示

Id   Fund    Date        SumOfAmount
1     A    02/28/2015      550
2     A    03/30/2015      600
3     B    04/01/2015     1100

如果我将您不正确的示例数据更改为...

CREATE TABLE TableName
    ([Id] int, [Fund] varchar(1), [Date] datetime, [Amount] int)
;

INSERT INTO TableName
    ([Id], [Fund], [Date], [Amount])
VALUES
    (1, 'A', '2015-01-28 00:00:00', 250),
    (2, 'A', '2015-01-28 00:00:00', 300),
    (3, 'A', '2015-03-30 00:00:00', 400),
    (4, 'A', '2015-03-30 00:00:00', 200),
    (5, 'B', '2015-04-01 00:00:00', 500),
    (6, 'B', '2015-04-01 00:00:00', 600)
;

这个使用 GROUP BY 的查询有效:

SELECT MIN(Id) AS Id,   
       MIN(Fund) AS Fund,
       [Date],        
       SUM(Amount) AS SumOfAmount
FROM dbo.TableName t
WHERE [Date] IN ('01/28/2015','03/30/2015','04/01/2015')
GROUP BY  [Date]

Demo

declare @TableName table([Id] int, [Fund] varchar(1), [Date] datetime, [Amount] int)
declare @Sample table([SampleDate] datetime)


INSERT INTO @TableName
    ([Id], [Fund], [Date], [Amount])
VALUES
    (1, 'A', '20150120 00:00:00', 250),
    (2, 'A', '20150128 00:00:00', 300),
    (3, 'A', '20150320 00:00:00', 400),
    (4, 'A', '20150330 00:00:00', 200),
    (5, 'B', '20150401 00:00:00', 500),
    (6, 'B', '20150401 00:00:00', 600)

INSERT INTO @Sample ([SampleDate])
values ('20150128 00:00:00'), ('20150330 00:00:00'), ('20150401 00:00:00')


-- select * from @TableName
-- select * from @Sample

;WITH groups AS ( 
    SELECT [Fund], [Date], [AMOUNT], MIN([SampleDate]) [SampleDate] FROM @TableName
    JOIN @Sample ON [Date] <= [SampleDate]
    GROUP BY [Fund], [Date], [AMOUNT])
SELECT [Fund], [SampleDate], SUM([AMOUNT]) FROM groups
GROUP BY [Fund], [SampleDate]

解释:

  • CTE groups 找到最早的 SampleDate 晚于(或等于)您的 数据的日期并相应地丰富您的数据,从而为他们提供要汇总的组。
  • 之后,您可以在派生日期进行分组。

最初我使用 Row_number 和月份函数来选择每个月的最大日期,在第二个 cte 中我做了金额的总和并加入了他们..可能是这个结果集与你的相匹配输出

declare @t table (Id int,Fund Varchar(1),Dated date,amount int)

insert into @t (id,Fund,dated,amount) values (1,'A','01/20/2015',250),
(2,'A','01/28/2015',300),
(3,'A','03/20/2015',400),
(4,'A','03/30/2015',200),
(5,'B','04/01/2015',600),
(6,'B','04/01/2015',500)

;with cte as (
select ID,Fund,Amount,Dated,ROW_NUMBER() OVER 
  (PARTITION BY DATEDIFF(MONTH, '20000101', dated)ORDER BY dated desc)AS RN from @t
  group by ID,Fund,DATED,Amount
  ),
  CTE2 AS 
  (select  SUM(amount)Amt from @t
    GROUP BY MONTH(dated))
  ,CTE3 AS 
  (Select Amt,ROW_NUMBER()OVER (ORDER BY amt)R from cte2)
 ,CTE4 AS 
 (
        Select DISTINCT C.ID As ID,
        C.Fund As Fund,
        C.Dated As Dated
        ,ROW_NUMBER()OVER (PARTITION BY RN ORDER BY (SELECT NULL))R
         from cte C INNER JOIN CTE3 CC ON c.RN = CC.R
        Where C.RN = 1
        GROUP BY C.ID,C.Fund,C.RN,C.Dated )

select C.R,C.Fund,C.Dated,cc.Amt  from CTE4 C INNER JOIN CTE3 CC
ON c.R = cc.R

根据您的问题,您似乎想要 select 一组日期,然后对于每个基金和 selected 日期,从 selected 日期到前一个 selected 日期。这是我认为您应该期待的结果集:

Fund    Date        SumOfAmount
A       2015-02-28  550.00
A       2015-03-30  600.00
B       2015-04-01  1100.00

这里是产生这个输出的代码:

DECLARE @Dates TABLE
(
    SelectedDate DATE PRIMARY KEY 
)

INSERT INTO @Dates 
VALUES
     ('02/28/2015')
    ,('03/30/2015')
    ,('04/01/2015')

DECLARE @FundAmounts TABLE
(
    Id INT PRIMARY KEY
    ,Fund VARCHAR(5)
    ,Date DATE
    ,Amount MONEY
);

INSERT INTO @FundAmounts
VALUES
     (1, 'A', '01/20/2015', 250)
    ,(2, 'A', '02/28/2015', 300)
    ,(3, 'A', '03/20/2015', 400)
    ,(4, 'A', '03/30/2015', 200)
    ,(5, 'B', '04/01/2015', 500)
    ,(6, 'B', '04/01/2015', 600);

SELECT 
    F.Fund
    ,D.SelectedDate AS Date
    ,SUM(F.Amount) AS SumOfAmount
FROM
(
    SELECT
        SelectedDate
        ,LAG(SelectedDate,1,'1/1/1900') OVER (ORDER BY SelectedDate ASC) AS PreviousDate
    FROM @Dates
) D
JOIN
    @FundAmounts F
    ON
        F.Date BETWEEN DATEADD(DAY,1,D.PreviousDate) AND D.SelectedDate
GROUP BY
    D.SelectedDate
    ,F.Fund

编辑:对于此示例,这里是 LAG 函数的替代方法:

FROM
(
    SELECT
        SelectedDate
        ,ISNULL((SELECT TOP 1 SelectedDate FROM @Dates WHERE SelectedDate < Dates.SelectedDate ORDER BY SelectedDate DESC),'1/1/1900') AS PreviousDate
    FROM @Dates Dates
) D