How to add a new column that summarize rows - sql

I have two issues :
I used 'Rollup' function to add Totals per Month and Year and I would like to change 'NULL' into grand_total as in the attached screenshot
I dont know how to add a new column that will summarize values starting from the second row
Please see attached screenshot of the results I need to receive and an example for a code from my side with a screenshot of the source output : [1]: https://i.stack.imgur.com/6B70o.png
[1]: https://i.stack.imgur.com/E2x8K.png
Select Year(Modifieddate) AS Year,
MONTH(modifieddate) as Month,
Sum(linetotal) as Sum_price
from Sales.SalesOrderDetail
Group by rollup( Year(Modifieddate),MONTH(modifieddate))
Thanks in advance,

I think this will work:
Select Year(Modifieddate) AS Year,
coalesce(convert(varchar(255), month(modifieddate)), 'Grand Total') as Month,
Sum(linetotal) as Sum_price,
sum(sum(linetotal)) over (partition by Year(Modifieddate)
order by coalesce(month(modifieddate), 100)
) as ytd_sum_price
from Sales.SalesOrderDetail
Group by rollup( Year(Modifieddate), month(modifieddate))
The coalesce() in the order by is to put the summary row last for the cumulative sum.

Like this:
Select Year(Modifieddate) AS Year, MONTH(modifieddate) as Month, Sum(linetotal) as Sum_price
from Sales.SalesOrderDetail
Group by rollup( Year(Modifieddate),MONTH(modifieddate))
UNION
Select Year(Modifieddate) AS Year, 'grand_total' as Month, Sum(linetotal) as Sum_price
from Sales.SalesOrderDetail
Group by Year(Modifieddate)

-- SQL SERVER
SELECT t.OrderYear
, CASE WHEN t.OrderMonth IS NULL THEN 'Grand Total' ELSE CAST(t.OrderMonth AS VARCHAR(20)) END b
, t.MonthlySales
, MAX(t.cum_total) cum_total
FROM (SELECT
YEAR(OrderDate) AS OrderYear,
MONTH(OrderDate) AS OrderMonth,
SUM(SubTotal) AS MonthlySales,
SUM(SUM(SubTotal)) OVER (ORDER BY YEAR(OrderDate), MONTH(OrderDate) ROWS UNBOUNDED PRECEDING) cum_total
FROM Sales.SalesOrderHeader
GROUP BY GROUPING SETS ((YEAR(OrderDate), MONTH(OrderDate)))) t
GROUP BY GROUPING SETS ((t.OrderYear
, t.OrderMonth
, t.MonthlySales), t.OrderYear);
Please check this url https://dbfiddle.uk/?rdbms=sqlserver_2019&sample=adventureworks&fiddle=e6cd2ba8114bd1d86b8c61b1453cafcf

To build one #GordonLinoff's answer, you are really supposed to use the GROUPING() function to check whether you are dealing with the grouping column. This behaves better in the face of nullable columns.
Select case when grouping(Year(Modifieddate)) = 0
then Year(Modifieddate)
else 'Grand Total' end AS Year,
case when grouping(month(modifieddate)) = 0
then convert(varchar(255), month(modifieddate))
else 'Grand Total' end as Month,
Sum(linetotal) as Sum_price,
sum(sum(linetotal)) over (
partition by
grouping(Year(Modifieddate)),
grouping(month(modifieddate)),
Year(Modifieddate)
order by month(modifieddate)
) as ytd_sum_price
from Sales.SalesOrderDetail
Group by rollup( Year(Modifieddate), month(modifieddate));

Related

Can't use order when grouped by in BigQuery

I want to group by FECHA_COMPRA and then order by the same field. But when I do this, I get an error message:
SELECT list expression references column FECHA_COMPRA which is neither grouped nor aggregated at [28:13]
This are the querys I'm using:
Select DATE(FECHA_COMPRA) as Date,TYPE,SUM(AMOUNT) AS Total, SUM(Quantity) as Qty FROM Test
GROUP BY DATE(FECHA_COMPRA)
Order by date(FECHA_COMPRA)
This is also not working:
Select DATE(FECHA_COMPRA) as Date,TYPE,SUM(AMOUNT) AS Total, SUM(Quantity) as Qty FROM Test
GROUP BY DATE(FECHA_COMPRA)
Order by FECHA_COMPRA
What is wrong?
Thanks!
Use below instead
select
date(fecha_compra) as date,
type,
sum(amount) as total,
sum(quantity) as qty
from test
group by date, type
order by date

I need help writing a query that shows the amount of orders for each month of the year and also the cumulative amount each year

I am so close to answering this question, but can't figure out the final bits.
I am using the AdventureWorks2019 database.
My code is:
with cte as
(
Select
year(orderdate) as "Years",
month(orderdate) as "Months",
sum(SubTotal) as "MonthlySales",
datepart(m, orderdate) as "MonthNumber"
from sales.SalesOrderHeader
group by year(orderdate), month(orderdate)
)
select
Years, Months, MonthlySales as "MonthlySales", sum(MonthlySales) over (partition by months order by MonthlySales
rows between unbounded preceding and current row) as "Cumulative"
from cte
group by Years, Months, MonthlySales
ORDER by Years, Months
I cant figure out how to order the 'over' part of the query. I know it needs to be "rows between unbounded preceding and current row", but because MonthlySales is sum(totaldue), adding it to another SUM() probably messes it up.
Honestly this question is pretty tough, and I gave it my best.
Thank you for your help!
You can use a window function directly in the aggregation:
Select year(orderdate) as Years, month(orderdate) as Months,
sum(SubTotal) as MonthlySales,
case when grouping(month(orderdate)) = 0
then sum(case when month(orderdate) is not null then sum(SubTotal) end) over (partition by year(orderdate) order bymonth(orderdate))
end as YTD_MonthlySales
from sales.SalesOrderHeader
group by grouping sets (
(year(orderdate), month(orderdate)),
(year(orderdate))
);
Please check and it'll return desired output.
-- SQL SERVER
SELECT t.OrderYear
, CASE WHEN t.OrderMonth IS NULL THEN 'Grand Total' ELSE CAST(t.OrderMonth AS VARCHAR(20)) END b
, t.MonthlySales
, MAX(t.cum_total) cum_total
FROM (SELECT
YEAR(OrderDate) AS OrderYear,
MONTH(OrderDate) AS OrderMonth,
SUM(SubTotal) AS MonthlySales,
SUM(SUM(SubTotal)) OVER (ORDER BY YEAR(OrderDate), MONTH(OrderDate) ROWS UNBOUNDED PRECEDING) cum_total
FROM Sales.SalesOrderHeader
GROUP BY GROUPING SETS ((YEAR(OrderDate), MONTH(OrderDate)))) t
GROUP BY GROUPING SETS ((t.OrderYear
, t.OrderMonth
, t.MonthlySales), t.OrderYear);
Also Check data from https://dbfiddle.uk/?rdbms=sqlserver_2019&sample=adventureworks&fiddle=e6cd2ba8114bd1d86b8c61b1453cafcf

T-SQL query to summarize sales for ALL YEARS: with total per month per year, and cumulative monthly amounts

I need to create a Sales Report that shows all years sales per month, and cumulative sales.
The database table is simple:
Transactions
(
ID INT,
TransactionDate DATETIME,
SalesAmount MONEY
)
I want the results to look similar to ExcelSheet below (I am showing only 2017/2018 amounts, but actual query needs to return results for all available years according to TransactionDate)
This is aggregation and a cumulative sum:
select year(TransactionDate), month(TransactionDate),
sum(SalesAmount),
sum(sum(SalesAmount)) over (partition by year(TransactionDate) order by min(TransactionDate))
from Transactions
group by year(TransactionDate), month(TransactionDate)
order by year(TransactionDate), month(TransactionDate);
Try it:
With Q
as
(
Select DatePart(yyyy,TransactionDate) 'Year',DatePart(m,TransactionDate) 'Month', sum(SalesAmount) 'Sales'
From Transactions
Group by DatePart(yyyy,TransactionDate),DatePart(m,TransactionDate)
)
Select q.Year,q.Month,q.sales,( Select sum(q1.Sales)
From Q q1
Where q1.Year=q.Year
And q1.Month <= q.Month
) 'Cumulative Sale'
From Q q
Order by q.Year,q.Month
Try this:
with cte as
(
select year(TransactionDate) as Year, month(TransactionDate) as Month, SalesAmount
)
select a.Year, a.Month, a.SalesAmount, sum(b.SalesAmount) as cumulativeSalesAmount
from Transactions a inner join Transactions b on a.STORE_ID = b.STORE_ID and a.Year = b.Year and a.Month >= b.Month
group by a.Year, a.Month
order by 1, 2

SQL YTD and last year YTD on complete data

I need to calculate YTD and last year YTD on a table [SQL Server 2012]. Below is the query I tried. Its getting doubled and tripled for some cases.
SELECT SUM(A.RevisionNumber)YTD,SUM(P.RevisionNumber)LY_YTD,B.OrderDateM,B.OrderDateY
FROM
(select MONTH(OrderDate)OrderDateM,YEAR(OrderDate)OrderDateY from sales.SalesOrderHeader B
group by MONTH(OrderDate),YEAR(OrderDate))B
LEFT JOIN
(select SUM(RevisionNumber)RevisionNumber,MONTH(OrderDate)OrderDateM,YEAR(OrderDate)OrderDateY
from sales.SalesOrderHeader
group by MONTH(OrderDate),YEAR(OrderDate))A
ON A.OrderDateM<=B.OrderDateM AND A.OrderDateY=B.OrderDateY
LEFT JOIN
(select SUM(RevisionNumber)RevisionNumber,MONTH(OrderDate)OrderDateM,YEAR(OrderDate)OrderDateY
from sales.SalesOrderHeader
group by MONTH(OrderDate),YEAR(OrderDate))P
ON P.OrderDateM<=B.OrderDateM AND P.OrderDateY=B.OrderDateY-1
GROUP BY B.OrderDateM,B.OrderDateY
ORDER BY B.OrderDateY,B.OrderDateM
You can use windowing function as below:
;With cte as (
Select Sum(RevisionNumber) As SM_RevisionNumber, Month(OrderDate) as OrderM,
Year(OrderDate) as OrderY
From Sales.SalesOrderHeader
Group by Month(OrderDate), Year(OrderDate)
), cte2 as (
Select YTD = Sum(SM_RevisionNumber) over (partition by OrderY order by OrderM),
OrderM, OrderY, RowN = Row_Number() over(order by OrderY, OrderM)
from cte
)
Select YTD, LY_YTD = lag(YTD, 12, null) over(Order by RowN), OrderM, ORderY
from cte2
But this solution assumes we have atleast one entry for each month and year.

Showing all results even using GROUP BY CLAUSE

Query :
How to sort by months ?
select format(datee,'mmm-yyyy') as [Months],sum(amount) as Amount
from ledger_broker
where ref_from like 'Purchase'
group by format(datee,'mmm-yyyy')
order by format(datee,'mmm-yyyy') desc
Output :
Try grouping by the same exact column which you select:
SELECT t.[Months], t.Amount
FROM
(
SELECT MONTH(datee) AS theMonth, YEAR(datee) AS theYear,
FORMAT(datee,'mmm-yyyy') AS [Months], SUM(amount) AS Amount
FROM ledger_transporter
WHERE ref_from LIKE 'Purchase'
GROUP BY MONTH(datee), YEAR(datee), FORMAT(datee, 'mmm-yyyy')
) t
ORDER BY t.theYear DESC, t.theMonth DESC
One way to order by date is to select the numeric month and year in your query.
change group by datee to group by format(datee,'mmm-yyyy').
select distinct format(datee,'mmm-yyyy') as [Months], sum(amount) as Amount
from ledger_transporter
where ref_from like 'Purchase'
group by format(datee,'mmm-yyyy')
order by Month(datee)
The reason is that your date, which I assume is say 01-FEB-2016 and 02-FEB-2016, is different and if you group by it, you will get 2 different records for it.
However, for format(datee,'mmm-yyyy'), ie FEB-2016, both of these dates are same. Hence the mismatch