How to group by quarters(1 year = 4 quarters) in SQL? [closed] - sql

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
Question Description:Show for each customer and product combination, the average sales quantities for 4 quarters,Q1, Q2, Q3 and Q4(in four separate columns) –Q1 being the first 3 months of the year (Jan, Feb & Mar), Q2 the next 3 months (Apr, May & Jun), and so on–ignore the YEAR component of the dates (i.e., 3/11/2001is considered the same date as 3/11/2002, etc.).Also compute the average for the “whole” year(again ignoring the YEAR component, meaning simply compute AVG) along with the total quantities(SUM) and the counts(COUNT).
table as follow:enter image description here
The sample result:enter image description here
I am a beginner on SQL and I met such a problem. It needs to group the 4 quarters just by using aggregate functions and group by clause.

with cte as (
select
customer,
product,
case
when (month < 4) then 'Q1'
when (month >= 4 AND month < 7) then 'Q2'
when (month >= 7 AND month < 10) then 'Q3'
when (month >= 10) then 'Q4'
end AS quarter,
quant
from bgg.table_sof
),
cte_full as (
select
customer,
product,
avg(quant) as average,
sum(quant) as total,
count(quant) as count
from bgg.table_sof
GROUP BY customer, product
)
select
cte_full.customer,
cte_full.product,
avg(cte1.quant) as Q1_AVG,
avg(cte2.quant) as Q2_AVG,
avg(cte3.quant) as Q3_AVG,
avg(cte4.quant) as Q4_AVG,
average,
total,
count
from cte_full
left join cte cte1 on cte_full.customer = cte1.customer and cte_full.product = cte1.product
left join cte cte2 on cte_full.customer = cte2.customer and cte_full.product = cte2.product
left join cte cte3 on cte_full.customer = cte3.customer and cte_full.product = cte3.product
left join cte cte4 on cte_full.customer = cte4.customer and cte_full.product = cte4.product
where cte1.quarter = 'Q1' OR cte2.quarter = 'Q2' OR cte3.quarter = 'Q3' OR cte4.quarter = 'Q4'
group by cte_full.customer, cte_full.product, average, total, count;
It's a tricky task for a beginner. My advice is to start with some theory and easy practice.
There is two CTE (common table expression):
the first is for defining quarters from months.
the second (cte_full) for calculating the last 3 columns in the result table.
And final select joins separately calculated avg by quarters to result.
I'm sure it isn't easy for understanding for beginner, feel free to ask.

Related

arithmetic operation on alias of column of table [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed last month.
Improve this question
I have written a query which fetch the data like this and I wanted to calculate the opening and maindata I have formula for then which is ( CurrentEmp + Empjoined - EmpLeft ) as opening and ((EmpLeft*100)/((CurrentEmp+opening)/2)) as maindata respectively I have written it in query but I gets the error saying invalid column name .
month year CurrentEmp join leftemp
January 2021 10 2 1
February 2021 15 3 2
March 2021 20 5 2
and the output that I expect is
month year CurrentEmp join leftemp opening
January 2021 10 2 1 11
February 2021 15 3 2 16
March 2021 20 5 2 23
I have written the below code
with t0(n) as ( select n from ( values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) t(n)),ns as(select row_number()
over(order by t1.n) - 1 n from t0 t1, t0 t2, t0 t3),calendar as (
select top(12) DATEADD(month, n, '2021-01-01' ) dt , DATEADD(month, n , '2021-01-31')dd from ns order by n) select cast(DATENAME(month, dt) as nvarchar(max)) AS month,cast(DATENAME(YEAR, dt) as nvarchar(max))AS Year,
(SELECT COUNT(*) FROM EmployeeDetail e left join Separation s on e.Id = s.EmployeeId
WHERE (e.CompanyId=1 and e.DateOfJoining <calendar.dt and e.EmpStatus = 1) or(s.CompanyId = 1 and e.DateOfJoining <calendar.dt and s.LastWorkingDate >= calendar.dt)) AS CurrentEmp,
(select count(*) from EmployeeDetail where DateOfJoining >=calendar.dt And DateOfJoining<=calendar.dd and CompanyId = 1) as Empjoined,
(select count(*) from Separation where LastWorkingDate >= calendar.dt and LastWorkingDate < =calendar.dd and CompanyId =1) as EmpLeft,
(CurrentEmp+Empjoined-EmpLeft) as opening , cast (((EmpLeft*100)/((CurrentEmp+opening)/2)) as decimal(10,2)) as maindata
from calendar order by dt
An alias in the current select statement cannot be used as a variable within that same select statement.
You'll need to either:
Repeat the calculation:
(CurrentEmp+Empjoined-EmpLeft) as opening,
-- NOTE: opening IS REPLACED BY SAME CALC: (CurrentEmp+Empjoined-EmpLeft)
cast (((EmpLeft*100) /
((CurrentEmp+(CurrentEmp+Empjoined-EmpLeft))/2))
as decimal(10,2)) as maindata
Or, move the primary calculation of opening to a sub-query and join on that.
But, given the simplicity and low overhead of the calculation, I'd just repeat the calculation.

SQL help to display no. of openings for all branches for each month of a year

Hi I need to generate a SSRS report to show how many centers got opened for each month in a calendar year under each branch. report will have 13 columns, first column being all the branches in each row and remaining 12 columns will have months of an year as header. I'm trying to get a result of each branch having no. of openings per month, so I can feed SSRS to display in tabular format. If a branch doesnt have any openings for any month, I need to display 0.
Branch table
=============
Branchid
Branchname
CenterOpen table
================
CenterOpenID
BranchID
CenterOpenDate
below is the SQL I had written
WITH months(MonthNumber) AS (
SELECT
1
UNION ALL
SELECT
MonthNumber + 1
FROM
months
WHERE
MonthNumber < 12
),
cteBranch(BranchID, BranchName, TargetOpenDate, Month, Count) as (
SELECT
B.BranchID,
B.BranchName,
CS.TargetOpenDate,
MONTH(CS.TargetOpenDate) as Month,
count(Month(CS.TargetOpenDate)) as Count
FROM
Branch B
left join goal.CenterOpenSchedule CS ON CS.BranchID = B.BranchID
GROUP BY
B.BranchID,
B.BranchName,
CS.TargetOpenDate,
MONTH(CS.TargetOpenDate)
)
select
*
from
months
cross join cteBranch
order by
BranchID asc,
MonthNumber asc
If I use cross join, months are repeating for each branch, how to resolve this? your help is highly appreciated.
Not sure which database you are on.
There are different ways to extract month/year from date.
Based on your example SQL, I'm going to use MONTH()
select branchName,
count(case when month(centerOpenDate) = 1 then branchId end) Jan_Count
...
...
count(case when month(centerOpenDate) = 12 then branchId end) Dec_Count
from Branch b
join CenterOpen co
on (b.BranchId = co.BranchId)
where year(centerOpenDate) = <your year filter>
group by branchName
This will take care of your below requirements:
" first column being all the branches in each row and remaining 12 columns will have months of an year as header."
and also -
"If a branch doesnt have any openings for any month, I need to display 0."
Your question is not explicit, but you seem to want a single year -- so you need to filter on the year.
The rest is basically conditional aggregation:
select b.branchName,
sum(case when month(co.centerOpenDate) = 1 then 1 else 0 end) as jan,
sum(case when month(co.centerOpenDate) = 2 then 1 else 0 end) as feb,
. . .
sum(case when month(co.centerOpenDate) = 12 then 1 else 0 end) as dec
from Branch b join
CenterOpen co
on b.BranchId = co.BranchId
where year(co.centerOpenDate) = #year
group by b.branchName

bring many years (oracle plsql) [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
hi this query bring for "one year 2020" ; but, i want to bring this query.
state_name ,2020 total deaths ,2021 total deaths
One option might be
select
s.statename,
sum(case when extract(year from st.date_) = 2020 then st.death end) deaths_2020,
sum(case when extract(year from st.date_) = 2021 then st.death end) deaths_2021
from statecases1 st join state_ s on s.statecode = st.statecode
group by s.statename
order by s.statename;
Your query can't return data for 2020 and 2021 because of the WHERE clause you used (you restricted dates to year 2020).
You can use this. Although i am not 100% clear but this is what i thought you need - sum by state and year. You can also use pivot.
WITH yearly_data AS
(SELECT s.statename, to_char(st.date_, 'YYYY') AS YEAR, sum(death) death
FROM covid.statecases1 st
JOIN covid_state_ s ON s.statecode=st.statecode
GROUP BY s.statename, to_char(st.date_, 'YYYY'))
SELECT DISTINCT a.statename, b.death 2020_death,c.death 2021_death
FROM yearly_data a
LEFT JOIN yearly_data b ON a.statename=b.statename AND b.year='2020'
LEFT JOIN yearly_data c ON a.statename=c.statename AND c.year='2021'
ORDER BY 1

Is there a way to split sql results by year?

I currently have the following SQL statement:
SELECT
[Manager].[Name],
COUNT([Project].[ProjectId]) AS TotalProjects
FROM
([Project]
INNER JOIN
[Manager] ON [Project].[ManagerId] = [Manager].[ManagerId])
WHERE
[Project].[CurrentStatusId] = 5
GROUP BY
[Manager].[Name]
It currently spits out total projects by each manager. I would like to have it split the projects out by the years they were completed. So basically count the total projects for each manager for each year (2016, 2017, and so on), as well as the total projects all time. I can use the column [Project].[CurrentStatusDt] for the date.
Just add the project year to the SELECT and GROUP BY clauses:
SELECT
[Manager].[Name],
YEAR([Project].[CurrentStatusDt]) PojectYear,
COUNT([Project].[ProjectId]) AS TotalProjects
FROM [Project]
INNER JOIN [Manager] ON [Project].[ManagerId] = [Manager].[ManagerId]
WHERE [Project].[CurrentStatusId] = 5
GROUP BY [Manager].[Name], YEAR([Project].[CurrentStatusDt])
Side note: you don't need parentheses around the joins in SQL Server (this is a MS Access limitation).
EDIT
If you want to spread the years over columns instead of rows, then one solution is to use conditional aggregation
SELECT
[Manager].[Name],
SUM(CASE
WHEN [Project].[CurrentStatusDt] < CAST('2019-01-01' AS DATE)
THEN 1
ELSE 0
END) TotalProjects2018,
SUM(CASE
WHEN [Project].[CurrentStatusDt] >= CAST('2019-01-01' AS DATE)
THEN 1
ELSE 0
END) TotalProjects2019
FROM [Project]
INNER JOIN [Manager] ON [Project].[ManagerId] = [Manager].[ManagerId]
WHERE
[Project].[CurrentStatusId] = 5
AND [Project].[CurrentStatusDt] >= CAST('2018-01-01' AS DATE)
AND [Project].[CurrentStatusDt] < CAST('2020-01-01' AS DATE)
GROUP BY [Manager].[Name]

Trouble with Select statement [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have a following select query That runs well
SELECT
division,
division_name,
object_account,
account_description,
Sum(value) AS PreferedSpend
FROM jde_dw.blanket_rpt
WHERE division = 02
AND vendor_type = 'PV'
AND month = 07
AND year = 2013
GROUP BY division, division_name, object_account, account_description
ORDER BY division
Now I want to add a column that shows total spend it would be the same query as above but without the vendor_type condition in the where statement.
So the final query will show Division, division_name, Object_account, Account_Description, Value( as preferred ) and value as( total which includes everything)
How can I do this?
Move the condition inside the SUM() so that only matching rows contribute to the sum:
SELECT
division,
division_name,
object_account,
account_description,
SUM(CASE WHEN vendor_type = 'PV' THEN value ELSE 0 END) as PreferedSpend,
SUM(value) AS TotalSpend
FROM jde_dw.blanket_rpt
WHERE division = 02
AND month = 07
AND year = 2013
GROUP BY division, division_name, object_account, account_description
ORDER BY division