Saif ali Karedia
Saif ali Karedia

Reputation: 912

Order by year, month along with cumulative sum

My table "DATA123" is as follows

NoticeDate------Amount
2016-02-14------60000
2015-11-06------10000
2015-12-02------10000
2016-01-13------50000
2016-01-24------10000
2015-12-29------30000
2016-01-12------20000
2015-11-18------50000

I want the output to be as

Year----month----Amount----Cumulative
2015----NOV------60000------60000
2015----DEC------40000------100000
2016----JAN------80000------180000
2016----FEB------60000------240000

In short i want orderly monthly report sql query (not procedure) with cumulative sum. However, I dont have a unique id representing each record.

Upvotes: 1

Views: 3051

Answers (4)

Siyavash Hamdi
Siyavash Hamdi

Reputation: 3087

Using WITH keyword, execute following query:

WITH cte AS 
( 
    SELECT  YEAR(NoticeDate) AS [Year], 
            Month(NoticeDate) AS [Month], 
            Amount 
    FROM    DATA123 
), 

kte AS 
( 
    SELECT  ROW_NUMBER() OVER (ORDER BY [Year], [Month]) as RowNumber, 
            [Year], 
            [Month], 
            SUM(Amount) AS Amount 
    FROM    cte 
    GROUP   BY [Year], [Month] 
) 

SELECT  (SELECT [Year]  FROM kte WHERE RowNumber = t1.RowNumber) AS [Year],
        (SELECT UPPER(CONVERT(CHAR(3), CAST('2000-' + CAST((SELECT [Month]  FROM kte WHERE RowNumber = t1.RowNumber) AS NVARCHAR(2)) + '-01' AS DATE), 0)))  AS [Month], 
        t1.Amount, 
        SUM(t2.Amount) AS Cumulative 
FROM    kte t1 
JOIN    kte t2 ON t1.RowNumber >= t2.RowNumber 
GROUP   By t1.RowNumber, t1.Amount 
ORDER   BY t1.RowNumber 


By executing above query, following result should be got:

+-------------------------------------+
| Year | Month |  Amount | Cumulative |
|------+-------+---------+------------+
| 2015 |  NOV  |  60000  |   60000    |
| 2015 |  DEC  |  40000  |   100000   |
| 2016 |  JAN  |  80000  |   180000   |
| 2016 |  FEB  |  60000  |   240000   |
+-------------------------------------+

Upvotes: 0

trincot
trincot

Reputation: 350242

I would suggest this query:

select datepart(year, NoticeDate1) Year,
       format(NoticeDate1,'MMM') Month,
       Amount,
       sum(Amount) over (order by NoticeDate1
                         rows unbounded preceding) Cumulative
from (
    select   dateadd(month, datediff(month, 0, NoticeDate), 0) NoticeDate1,
             sum(amount) Amount
    from     data123
    group by dateadd(month, datediff(month, 0, NoticeDate), 0)
) a

It produces this output for the sample data:

| Year | Month | Amount | cumulative |
|------|-------|--------|------------|
| 2015 |   Nov |  60000 |      60000 |
| 2015 |   Dec |  40000 |     100000 |
| 2016 |   Jan |  80000 |     180000 |
| 2016 |   Feb |  60000 |     240000 |

SQL fiddle

The query makes use of windows functions with rows unbounding preceding, which is the key for cumulative sums. NoticeData1 is the first day of the month for date NoticeDate. The format function can be used to get month names.

You might want to add an order by clause, but then you better select the month number, because month names don't sort like you would want :). Still the sort order will be OK like it is now. The engine needs the correct sort order for the cumulative sum, so it has no reason to change it.

Upvotes: 2

sgeddes
sgeddes

Reputation: 62841

Since you're using 2012, here's one option using window functions:

select
    yr,
    mth,
    sumamount,
    sum(sumamount) over (order by yr, mth rows unbounded preceding) runningsum
from (select year(noticedate) yr,
             month(noticedate) mth,
            sum(amount) sumamount
      from data123
      group by year(noticedate), month(noticedate)
) t
order by yr, mth

Upvotes: 2

David Riega
David Riega

Reputation: 1

You can use the DATEPART or DATENAME function, and also generate the row number with the ROW_NUMBER:

SELECT A.DataRowNumber, A.[year], A.[month], A.[day], A.[Ammount], SUM(B.[Ammount]) FROM (SELECT ROW_NUMBER() OVER (ORDER BY [NoticeDate]) AS 'DataRowNumber', DATEPART(YEAR, [NoticeDate]) AS 'year',DATENAME(MONTH, [NoticeDate]) AS 'month', DATEPART(DAY, [NoticeDate]) AS 'day',[Ammount]
      FROM [dbo].[DATA123]) A INNER JOIN (SELECT ROW_NUMBER() OVER (ORDER BY [NoticeDate]) AS 'DataRowNumber', DATEPART(YEAR, [NoticeDate]) AS 'year',DATENAME(MONTH, [NoticeDate]) AS 'month', DATEPART(DAY, [NoticeDate]) AS 'day',[Ammount]
      FROM [dbo].[DATA123]) B
ON A.[DataRowNumber] >= B.[DataRowNumber]
GROUP BY A.[DataRowNumber], A.[year], A.[month], A.[day], A.[peso_factura]

Upvotes: 0

Related Questions