根据给定条件总结记录

时间:2015-04-02 14:14:33

标签: sql sql-server vba ms-access

我有一张如下表所示,对于任何特定基金我需要的是什么,直到任何特定日期逻辑将总和金额值。假设我需要3个日期的总和作为01/28 / 2015,03 / 30/2015和04/01/2015。然后逻辑将检查第一个日期表中有多少条记录。如果它找到多个记录,那么它将对金额值求和。然后,对于下一个日期,它将总结到下一个日期,但是从上一个日期开始总结。

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

4 个答案:

答案 0 :(得分:1)

如果我将不正确的样本数据更改为...

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

答案 1 :(得分:1)

根据您的问题,您似乎想要选择一组日期,然后针对每个基金和所选日期,获取从所选日期到上一个选定日期的基金金额总和。以下是我认为您应该期待的结果集:

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

答案 2 :(得分:0)

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晚于(或等于)您的{{1}} 数据的日期并相应地丰富您的数据,从而为他们提供总结的小组。
  • 之后,您可以对派生日期进行分组。

答案 3 :(得分:0)

最初我使用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