Sql query for monthly/yearly report - sql

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)

Related

Total hours worked for employees in 2018 and 2019

I am new to stackoverflow and new to sql. I have employee timesheets which has a unique id and hours works by employees. I was wondering if theres a way to calculate the sum of the hours for each employee in 2018.
I dont know if this query is too basic but what i have so far is this:
select distinct PersonId, SUM(reghours) as '2018'
from TimeSheetsView
where left(yearweek,4)='2018'
group by PersonId, reghours
If you wanted to sum up both 2018 and 2019 in their own columns you could use a case statement to target those specific records in 2018 and 2019 placing them in their own column. You don't need a distinct with the group by either and like Mitch said you don't need that reghours it will split aggregation.
In the THEN piece it will sum up that field and ELSE is 0 so it won't obviously sum up any other rows that don't meet that condition.
Select PersonId
, SUM(CASE WHEN left(yearweek,4)='2018' THEN reghours ELSE 0 END) as '2018_RegHours'
, SUM(CASE WHEN left(yearweek,4)='2019' THEN reghours ELSE 0 END) as '2019_RegHours'
from TimeSheetsView
where left(yearweek,4) IN ('2018', '2019')
group by PersonId

Running total for grouped data 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.

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.

SQL count records depending on criteria

I have a table which has account information for each individual working day. Each record shows the balance on the account for that particular day. I need to create a field that has a running count on how many days it has been since the balance on that particular account was zero.
For example: I have an account which is number 00000001. It was opened a week ago. The database has created a record for the account for last Tuesday, Wednesday, Thursday, Friday and Monday. The account did not have a balance until Friday and the balance was the same for Monday. I want the field to show '2' as a result. Further to this if the balance drops to '0' today, I need the count to reset on the next record and start again if the account has a balance the following day. There are several accounts in this table so I need this to work for each one individually.
Below is as far as I have got:
SELECT
pos.EffDate,
cus.CNA1,
pos.ACNO,
pos.CCY,
pos.LDBL,
pos.LDBLUSD,
MIN(pos3.effdate) AS 'First Post Date',
pos3.Balcount
FROM[dbo].[Account] AS pos
JOIN [dbo].[Customer] AS cus ON ((pos.CNUM=cus.CUST_NO) AND (cus.effdate=pos.effdate))
LEFT JOIN (SELECT pos2.effdate, pos2.ACNO, SUM(CASE pos2.LDBL WHEN 0 THEN 0 ELSE 1 END) AS 'Balcount' FROM [dbo].[Account] AS pos2 GROUP BY pos2.ACNO, pos2.Effdate HAVING pos2.effdate BETWEEN pos2.effdate AND MIN(pos2.effdate)) pos3 ON pos3.ACNO = pos.ACNO
WHERE pos.effdate >='1 Dec 2015' AND pos.Effdate <'30 Dec 2015'
AND pos.srcsys = 'MP_UK'
AND pos.LDBL <= 0
AND pos.CNUM <> '000020'
AND pos.intbear <> 'N'
AND pos.blockdeb IS null
GROUP BY pos.EffDate,cus.CNA1,pos.ACNO,pos.CCY,pos.LDBL,pos.LDBLUSD, pos3.Balcount
ORDER BY 1,2,3
If you need me to clarify anything please let me know. All help is greatly appreciated.
Thanks,
Ben
Basically, you want to group the data, based on the number of time the account is zero before a given row. Then, within each group, you want to enumerate the records.
In SQL Server 2012+, you can do these things with window functions. I am not sure exactly what your sample query has to do with the question, but here is the basic idea:
select a.*, row_number() over (partition by cust_no, grp order by eff_date) as seqnum
from (select a.*,
sum(case when balance = 0 then 1 else 0 end) over
(partition by cust_no order by eff_date) as grp
from Account a
) a;
In earlier versions of SQL Server, you can do something very similar using apply.

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.