Running total for grouped data SQL - sql

I know there are a lot of questions about this and I have tried a lot of the answers but none have worked for me yet (see below for the most promising).
I want to get the running total in the column amount grouped by project and date divided into two groups (invoiced or costs). The group is dependent on the Cost Center as you can see in the query.
This topic has seemed to be the closest to what I'm trying to achieve but I cant get it to work.
SQL - running total when data already grouped
With the code below I get the error message "Column 'M3FDBPRD.MVXJDTA.FGLEDG.EGAIT2' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause." But I don't want to group by cost center in the result, I only want to use it to group the amount.
The reuslt im trying to achevie is this (if using the data above):
My current code is this:
SELECT
Project As Projektnr,
LastDayOfMonth,
-SUM(CASE WHEN CostCenter= '9000' THEN Amount
WHEN CostCenter = '2100' THEN Amount
WHEN CostCenter = '2200' THEN Amount
WHEN CostCenter = '2300' THEN Amount END) OVER (ORDER BY LastDayOfMonth) AS Invoiced,
-SUM(CASE WHEN CostCenter > '9000' and CostCenter < '9999' THEN Amount END) OVER (ORDER BY LastDayOfMonth) AS RunningTotalCosts
FROM [M3FDBPRD].[MVXJDTA].[FGLEDG]
WHERE Project = '150001'
GROUP BY LastDayOfMonth, Project
ORDER BY LastDayOfMonth
I have SQL Server version 13
Thank you

You are mixing window functions and aggregation. The logic looks like:
SUM(SUM(CASE WHEN CostCenter IN ('9000' '2100', '2200', '2300')
THEN Amount
END)
) OVER (ORDER BY LastDayOfMonth) AS Invoiced,
SUM(SUM(CASE WHEN CostCenter > '9000' and CostCenter < '9999'
THEN Amount
END)
) OVER (ORDER BY LastDayOfMonth) AS RunningTotalCosts
That is, the SUM()s need to nested. The inner SUM() is the aggregation. The outer SUM() is the window function.

Related

Average of maximum

I am new to sql and tried to find similar topic, but with no success.
If someone could help, I will be very grateful:-)
Here is a tiny part of big code, which is based on Group by 1 column 'CustomerID' (and I do not need more!).
I need to calculate Maximum of [Field] per each year and afterwards arrive at average of those MAX values.
SELECT
t0.[CustomerID]
,MAX(t0.[CustomerName]) as 'CustomerName'
,SUM(CASE WHEN t0.[Year] = 2021 then t0.[SalesValue_USD] END) as 'Sales_USD_2021'
,SUM(t0.[SalesValue_USD]) as 'Sales_USD_total'
,AVG(MAX(t0.[Field]) OVER (PARTITION BY [Year])) as 'Field_avr'
From market t0
Where [Year] in (2019,2020,2021)
Group by t0.[CustomerID]
You can do it in two steps
SELECT [CustomerID],
MAX('CustomerName') as 'CustomerName',
SUM('Sales_USD_2021') as 'Sales_USD_2021',
SUM('Sales_USD_total') as 'Sales_USD_total',
AVG(Field_max) as 'Field_avr'
FROM (
SELECT
t0.[CustomerID], t0.[Year]
,MAX(t0.[CustomerName]) as 'CustomerName'
,SUM(CASE WHEN t0.[Year] = 2021 then t0.[SalesValue_USD] END) as 'Sales_USD_2021'
,SUM(t0.[SalesValue_USD]) as 'Sales_USD_total'
,MAX(t0.[Field]) as 'Field_max'
From market t0
Where [Year] in (2019,2020,2021)
Group by t0.[CustomerID], t0.[Year] ) t
Group by [CustomerID]

How to get the asked columns for each customers

I have this table called table a
I need to get the CustomerID, sum(Income) of 2015, sum(Income) of 2016, did he ever bought productId A (boolean), is the total sum(income)> 1000 (boolean), number of total InvoiceID
all that in one query and the results should be with 1 row per customer.
please help I don't even know how to start!
This is basically conditional aggregation:
select customerid,
sum(case when extract(year from date) = 2015 then sales end) as sales_2015,
sum(case when extract(year from date) = 2016 then sales end) as sales_2016,
max( product = 'A' ) as ever_bought_a,
sum(income) > 1000 as sum_exceeds_1000,
count(*) as num_invoices
from t
group by customerid;
You haven't specified a database, so this is really psuedocode. You'll need to adapt it for your particular database.

Share of invoiced in total (sum group by)

I have sales lines some of them are invoiced, some not. I would like to add information of invoiced lines share per each order (salesid). I want this information for each sales line to be the same within one order. Invoiced line has sales status =3. Here's my try:
SELECT
salesid,linenum,itemid,salesstatus,name,lineamount
,(SELECT SUM(CASE WHEN salesstatus=3 THEN lineamount ELSE 0 END) as expr1) invoiced
,(SELECT SUM (lineamount) as expr2 GROUP BY salesid) total
,invoiced/total
FROM T.SALESLINES
GROUP BY
salesid,linenum,itemid,salesstatus,name,lineamount
Grouping by salesid does not work giving error "Each GROUP BY expression must contain at least one column that is not an outer reference."
I guess the code seems logical but does not work. So how should I group by salesid to divide invoiced by total?
try
Select *,invoiced/total as ColName from (
SELECT
salesid,linenum,itemid,salesstatus,name,lineamount
,(SELECT SUM(CASE WHEN salesstatus=3 THEN lineamount ELSE 0 END From T.SALESLINES) as invoiced
,(SELECT SUM (lineamount)From T.SALESLINES GROUP BY salesid) as total
FROM T.SALESLINES) source
GROUP BY
salesid,linenum,itemid,salesstatus,name,lineamount,invoiced,total

Sql query for monthly/yearly report

I have got a Sales table which has fields like
upgrade[yes/no]
date upgraded[datetime]
user[username]
What I want to run a query and show upgrades monthly and yearly wise , for instance i want to generate a report like Jan 2012 [total upgrades made 30, user1 made 10 upgrades , user 2 made 15 upgrades, similarly
user 3 made 5 upgrades. Similarly I want to acheive that for yearly basis too.
Using SSRS, you could generate multiple groupings fairly easily and display all of this information at-a-glance.
In a vanilla T-SQL query, you can do it like this:
SELECT
YEAR(s.[date upgraded]),
s.[user],
COUNT(*) AS [total upgrades]
FROM [Sales] s
WHERE s.[upgrade] = 'yes'
GROUP BY s.[user], YEAR(s.[date upgraded]) WITH ROLLUP
ORDER BY YEAR(s.[date upgraded]), s.[user]
SELECT
MONTH(s.[date upgraded]),
s.[user],
COUNT(*) AS [total upgrades]
FROM [Sales] s
WHERE s.[upgrade] = 'yes'
GROUP BY s.[user], MONTH(s.[date upgraded]) WITH ROLLUP
ORDER BY MONTH(s.[date upgraded]), s.[user]
SELECT USERNAME,
CONVERT(CHAR(7), DATE_FIELD,120) AS MONTH,
SUM(CASE WHEN UPGRADE = 'YES' THEN 1 ELSE 0 END) UPGRADED
FROM TABLE
GROUP BY USERNAME, CONVERT(CHAR(7), DATE_FIELD,120)

using count in a subquery and getting errors

i have line by line data in a table and i need to net of cancellations from sales and produce a report grouping on a scheme identifier. i.e i need to find all the sales and subtract all the cancellatsion to prduce a net sales figure.
i am trying to use the query below but i'm getting errors.
select insscheme, ((select count(quote_id) where (sale = '1')) - (select count(quote_id) where cancellation = '1')) as sales from policys
group by insscheme
order by insscheme
and i'm getting the error
Column 'policys.Sale' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Can anyone help me out with this?
You don't need any sub queries here. Just use COUNT and CASE.
SELECT insscheme,
COUNT(CASE WHEN sale = '1' AND cancellation <> '1' THEN 1 END) AS sales
FROM policys
GROUP BY insscheme
ORDER BY insscheme
I have assumed above that cancellation is not nullable. If it is use
COUNT(CASE WHEN sale = '1' THEN 1 END) -
COUNT(CASE WHEN cancellation = '1' THEN 1 END) AS sales
Perhaps this might work.
select insscheme, SUM(sale) - SUM(cancellation) as NetSales
from policys
group by insscheme
I don't see what the quote_id column has to do with your query. Are you querying one table or several? It would help if you could show us what your schema looks like with a brief discussion of your table layout.