Conditional Logic within SUM - sql

I'm currently combining two tables through a UNION ALL query and performing SUM and GROUP BY operations on the result. Everything is working as expected, but I have a unique requirement which I can't seem to figure out how to implement.
My aim is to write SQL that says "when DEV_AGE column is >= 12 set the REVENUE value to what it would be if this column was 12". I provide the code below as I know this description can be a bit confusing:
REVENUE table:
ACC_YR DEV_AGE STATE REVENUE LOSS
2012 3 MA 4000 0
2012 6 MA 8000 0
2012 9 MA 12000 0
2012 12 MA 16000 0
LOSS table:
ACC_YR DEV_AGE STATE REVENUE LOSS
2012 3 MA 0 2000
2012 6 MA 0 7000
2012 9 MA 0 9000
2012 12 MA 0 10000
2012 15 MA 0 14000
2012 18 MA 0 14000
2012 21 MA 0 14000
2012 24 MA 0 15000
2012 27 MA 0 17000
Table after UNION ALL, GROUP BY, SUM:
ACC_YR DEV_AGE STATE REVENUE LOSS
2012 3 MA 4000 2000
2012 6 MA 8000 7000
2012 9 MA 12000 9000
2012 12 MA 16000 10000
2012 15 MA 0 14000
2012 18 MA 0 14000
2012 21 MA 0 14000
2012 24 MA 0 15000
2012 27 MA 0 17000
What I WANT to accomplish:
ACC_YR DEV_AGE STATE REVENUE LOSS
2012 3 MA 4000 2000
2012 6 MA 8000 7000
2012 9 MA 12000 9000
2012 12 MA 16000 10000
2012 15 MA 16000 14000
2012 18 MA 16000 14000
2012 21 MA 16000 14000
2012 24 MA 16000 15000
2012 27 MA 16000 17000
In other words, my REVENUE stops developing at a DEV_AGE of 12 (there are no rows in the REVENUE table beyond a DEV_AGE of 12), but I want every DEV_AGE beyond 12 to equal what the REVENUE was at 12 in the final table.

Here is an approach that uses window functions to calculate the revenue for age 12 and then logic to assign it:
select acc_yr, dev_age, state,
(case when dev_age > 12 then rev12 else revenue end) as revenue, loss
from (select l.acc_yr, l.dev_age, l.state, r.revenue, l.loss,
max(case when l.dev_age = 12 then r.revenue end) over (partition by l.acc_yr, l.state) as rev12
from loss l left join
revenue r
on l.acc_yr = r.acc_yr and l.dev_age = r.dev_age and l.state = dev.state
) lr;

Related

Converting Weeknumber Fields into Rows

I have a table that is layed out as follows :
Code,Year, Wk1Val, Wk2Val, Wk3Val, Wk4Val etc to to Wk52Val.
Is there SQL to show the data as follows, without having to do 52 Case statements :
Code, Year, Week, Value
You can use UNPIVOT with REPLACE functions. Be sure to add all 52 week columns to the UNPIVOT IN portion of the query.
SELECT
u.Code,
u.Year,
REPLACE(REPLACE(u.Weeks, 'Wk', ''), 'Val', '') AS Weeks,
u.Value
FROM test
UNPIVOT
(
Value FOR Weeks IN (Wk1Val, Wk2Val, Wk3Val, Wk4Val, Wk52Val)
) AS u;
Fiddle here.
Input:
Code
Year
Wk1Val
Wk2Val
Wk3Val
Wk4Val
Wk52Val
1
2022
5000
15000
9000
4000
1000
2
2022
900
3200
7000
8500
9500
3
2022
3500
7800
10000
6200
5600
Output:
Code
Year
Weeks
Value
1
2022
1
5000
1
2022
2
15000
1
2022
3
9000
1
2022
4
4000
1
2022
52
1000
2
2022
1
900
2
2022
2
3200
2
2022
3
7000
2
2022
4
8500
2
2022
52
9500
3
2022
1
3500
3
2022
2
7800
3
2022
3
10000
3
2022
4
6200
3
2022
52
5600

Need to find count of profit and loss and no data using select subquery

I have the following table
Years Months Credit Debit ProfitandLoss Symbol
2019 Jan 10000 2000 1000 P
2019 Aug 8000 1000 -10922 L
2019 May 5000 3000 2000 P
2020 Feb 10000 5000 800 P
2020 Apr 1000 6000 0 N
2020 Oct 2000 1000 2000 P
2021 Jan 6000 8000 -600 L
2021 Mar 2000 3000 1400 P
2021 Nov 2000 2000 0 N
Here I need to calculate total credit, total debit, total profit and loss and total count of profit, total count of loss, total count of nothing in one result table.
I have tried this but cannot get CountOfProfit, CountOfLoss and CountNothing according to years.
select Years,
SUM(credit) as [Total Credit],
SUM(debit) as totaldebit,
COUNT(Symbol) as totalcredit,
(select COUNT(Symbol) from Yearly where Symbol='P') as CountofProfit,
(select COUNT(Symbol) from Yearly where Symbol='L') as CountofLoss,
(select COUNT(Symbol) from Yearly where Symbol='N')as CountNothing
from Yearly
group by Years
My result table should be like
Years TotalCredit TotalDebit TotalProfitandLoss CountOfProfit CountofLoss CountofNothing
2019 23000 7000 -7022 2 1 0
2020 13000 12000 2800 2 0 1
2021 10000 13000 800 1 1 1
You need use conditional aggregation. This is achieved with a CASE expression:
SELECT Years,
SUM(Credit) AS TotalCredit,
SUM(Debit) AS TotalDebit,
SUM(ProfitandLoss) AS TotalProfitAndLoss,
COUNT(CASE Symbol WHEN 'P' THEN 1 END) AS Profits,
COUNT(CASE Symbol WHEN 'L' THEN 1 END) AS Losses,
COUNT(CASE Symbol WHEN 'N' THEN 1 END) AS Nothings
FROM (VALUES(2019,'Jan',10000,2000, 1000 ,'P'),
(2019,'Aug',8000 ,1000,-10922,'L'),
(2019,'May',5000 ,3000, 2000 ,'P'),
(2020,'Feb',10000,5000, 800 ,'P'),
(2020,'Apr',1000 ,6000, 0 ,'N'),
(2020,'Oct',2000 ,1000, 2000 ,'P'),
(2021,'Jan',6000 ,8000, -600 ,'L'),
(2021,'Mar',2000 ,3000, 1400 ,'P'),
(2021,'Nov',2000 ,2000, 0 ,'N'))V(Years,Months,Credit,Debit,ProfitandLoss,Symbol)
GROUP BY Years
ORDER BY Years;

how to pivot dataframe to yield results by department and sum value

Is there a way to pivot following dataframe to get the results by departments and total opened days with sum.
Department 2012 2013 2014
0 Electronics 0 270 365
1 Electronics 0 0 0
2 Grocery 242 365 365
3 Grocery 241 365 365
Expected:
Department Year Total
0 Electronics 2012 0
1 Electronics 2013 270
2 Electronics 2014 365
2 Grocery 2012 483
2 Grocery 2013 730
2 Grocery 2014 730
We can do groupby with sum then stack
s=df.groupby('Department').sum().stack().to_frame('Total').reset_index()
Let's melt the data, groupby on Department and Year and sum to get our total :
(df.melt("Department",
var_name="Year",
value_name="Total")
.groupby(["Department","Year"])
.sum()
)
Total
Department Year
Electronics 2012 0
2013 270
2014 365
Grocery 2012 483
2013 730
2014 730

Count and where conditions leades to perfomance issues?

I am working on a million data rows table.The table look likes below
Departement year Candidate Spent Saved
Electrical 2013 A 50 50
Electrical 2013 B 25 50
Electrical 2013 C 11 50
Electrical 2013 D 25 0
Electrical 2013 Dt 86 50
Electrical 2014 AA 50 50
Electrical 2014 BB 25 0
Electrical 2014 CH 11 50
Electrical 2014 DG 25 0
Electrical 2014 DH 0 50
Computers 2013 Ax 50 50
Computers 2013 Bc 25 50
Computers 2013 Cx 11 50
Computers 2013 Dx 25 0
Computers 2013 Dx 86 50
I am looking output like below.
Departement year NoOfCandidates NoOfCandidatesWith50$save NoOfCandidatesWith0$save
Electrical 2013 5 4 1
Electrical 2014 5 3 2
Computers 2013 5 4 1
I am using #TEMP tables for every count where conditions and left outer joining at last .So it takes me more time.
Is there any way so i can perform better for above Table .
Thanks in advance.
You want to do this as a single aggregation query. There is no need for temporary tables:
select department, year, count(*) as NumCandidates,
sum(case when saved = 50 then 1 else 0 end) as NumCandidatesWith50Save
sum(case when saved = 0 then 1 else 0 end) as NumCandidatesWith00Save
from table t
group by department, year
order by 1, 2;

Join Three tables with Sum of column in access query

I have Three tables as shown below..
I need output as shown in output table
for this i need to join three tables and order output in month order
tbl_MonthList
MonthID MonthList
1 January
2 February
3 March
4 April
5 May
6 June
7 July
8 August
9 September
10 October
11 November
12 December
tbl_Amount:
Month_id Amount_Received Customer_id
3 500 aaa
3 1000 bbb
4 700 jjj
5 300 aaa
5 400 jjj
5 500 ppp
7 1000 aaa
10 1500 bbb
12 700 jjj
tbl_Month_Target
MonthID MonthF_L
1 10000
2 150000
3 1000
4 50000
5 5000
6 3000
7 20000
8 12000
9 34000
10 85000
11 34000
12 45000
I need output as shown below
Month Total_amount MonthF_L
January 0 10000
February 0 150000
March 2000 1000
April 700 50000
May 1200 5000
June 0 3000
July 1000 20000
August 0 12000
September 0 34000
October 1500 85000
November 0 34000
December 700 45000
SELECT ML.MonthList AS Month,
Sum(A.Amount_Received) AS Total_amount,
First(MT.MonthF_L) AS MonthF_L
FROM (tbl_MonthList AS ML
INNER JOIN tbl_Month_Target AS MT ON ML.MonthID = MT.MonthID)
LEFT JOIN tbl_Amount AS A ON ML.MonthID = A.Month_id
GROUP BY ML.MonthList, ML.MonthID
ORDER BY ML.MonthID
Note: In MS Access, multiple joins must be explicitly nested within parentheses
Try this:
select ml.MonthList, sum(a.Amount_Received), mt.MonthF_L from tbl_MonthList ml
left join tbl_Month_Target mt on mt.MonthID = ml.MonthID
left join tbl_Amount a on ml.Month_id = ml.MonthID
group by ml.MonthList, mt.MonthF_L