Getting value repeated for next year if value is recurring - sql
I have a record for project and release number and I need to repeat the row in next year if value is recurring.
First image is showing the data that I have it
My expected output is:
Explanation of output: In year 2017 value_type ITA has frequency as Recurring so, This value should be repeated in all next year(i.e 2018, 2019 and 2020). like that in year 2018 OC and PA is recurring so it also need to repeated in 2019 and 2020.
For that I created a new view for only recurring value and tried to join that view with base table. But it is not giving me proper result.
Can anyone please help me with this?
Thanks in advance..
DECLARE #EndYear INT =2020 --Also you can get from data by MAX(Year)
;WITH tb(PROJECT_ID,RELEASE_NO,[YEAR],VALUE_TYPE,VAL_DES,COST,RUN_TATE,FREQUENCY)
AS(
SELECT 111,1,2016,'IT','EXPENSE',0,NULL,NULL UNION
SELECT 111,1,2016,'IR','INCOME',10000,NULL,NULL UNION
SELECT 111,1,2016,'OC','EXPENSE',-200000,NULL,NULL UNION
SELECT 111,1,2016,'Vendor','EXPENSE',-5000,NULL,NULL UNION
SELECT 111,1,2017,'BC','INCOME',200000,NULL,NULL UNION
SELECT 111,1,2017,'ITA','INCOME',5000,5000,'Recurring' UNION
SELECT 111,1,2017,'OC','EXPENSE',-200000,NULL,NULL UNION
SELECT 111,1,2018,'OC','EXPENSE',-10000,-10000,'Recurring' UNION
SELECT 111,1,2018,'PA','INCOME',100000,100000,'Recurring' UNION
SELECT 111,1,2019,'icc','INCOME',500,NULL,NULL UNION
SELECT 111,1,2020,NULL,NULL,NULL,NULL,NULL
),Recurring AS (
SELECT tb.PROJECT_ID,tb.RELEASE_NO,tb.VALUE_TYPE,tb.VAL_DES,MIN([YEAR]) AS StartYear,MAX(COST) AS COST,MAX(tb.RUN_TATE) AS RUN_TATE
FROM tb WHERE FREQUENCY='Recurring'
GROUP BY tb.PROJECT_ID,tb.RELEASE_NO,tb.VALUE_TYPE,tb.VAL_DES
)
SELECT * FROM tb union
SELECT r.PROJECT_ID,r.RELEASE_NO,n.number AS [YEAR],r.VALUE_TYPE,r.VAL_DES,r.COST,r.RUN_TATE,NULL AS FREQUENCY FROM
Recurring AS r
OUTER APPLY (
SELECT sv.number FROM master.dbo.spt_values AS sv WHERE sv.type='P' AND sv.number BETWEEN r.StartYear+1 AND #EndYear
)n
PROJECT_ID RELEASE_NO YEAR VALUE_TYPE VAL_DES COST RUN_TATE FREQUENCY
----------- ----------- ----------- ---------- ------- ----------- ----------- ---------
111 1 2016 IR INCOME 10000 NULL NULL
111 1 2016 IT EXPENSE 0 NULL NULL
111 1 2016 OC EXPENSE -200000 NULL NULL
111 1 2016 Vendor EXPENSE -5000 NULL NULL
111 1 2017 BC INCOME 200000 NULL NULL
111 1 2017 ITA INCOME 5000 5000 Recurring
111 1 2017 OC EXPENSE -200000 NULL NULL
111 1 2018 ITA INCOME 5000 5000 NULL
111 1 2018 OC EXPENSE -10000 -10000 Recurring
111 1 2018 PA INCOME 100000 100000 Recurring
111 1 2019 icc INCOME 500 NULL NULL
111 1 2019 ITA INCOME 5000 5000 NULL
111 1 2019 OC EXPENSE -10000 -10000 NULL
111 1 2019 PA INCOME 100000 100000 NULL
111 1 2020 NULL NULL NULL NULL NULL
111 1 2020 ITA INCOME 5000 5000 NULL
111 1 2020 OC EXPENSE -10000 -10000 NULL
111 1 2020 PA INCOME 100000 100000 NULL
Related
How to get 100 records from a table with a value from year 2022 more than from year 2021
Here is the code that is working, but can it be more efficient and avoid subquery? condition used: (revenue_2022 - revenue_2021) > 0 or revenue_2022 > revenue_2021 select id from main_tbl where ( ( select revenue from main_tbl where id = ts.id and bq_year = 2022 and revenue > 0 ) - ( select revenue from main_tbl where id = ts.id and year = 2021 and revenue > 0 ) ) > 0 limit 100 main_table: id | revenue | year ---------------------- 1 | 4500 | 2022 1 | 4600 | 2021 2 | 3300 | 2022 3 | 5800 | 2022 3 | 5500 | 2021 expected output is the id 3 since its revenue for the year 2022 is greater than the year 2021 And 2 is not considered, since it doesn't have the year 2021 to compare with.
It's a little unclear what you'd like to do if there are other years, or more than one entry per id+year, but you could do something like: select id from main_table y2022, main_table y2021 where y2022.year = 2022 and y2021.year = 2021 and y2022.id = y2021.id and y2022.revenue > y2021.revenue limit 100
Need to pick up the SUM OF Tax Amount for the highest Sequence number Per Year, Per SSN, Per employer
Consider Employee table: Employerid ssn year Seqnumber q1taxamt q2taxamt q3taxamt q4taxamt 1004 101 2013 1 2000 0 0 0 1004 101 2013 2 2000 100 0 0 1004 101 2013 3 2000 100 200 0 1004 101 2013 4 2000 100 200 300 1004 102 2013 1 3000 0 0 0 1004 102 2013 2 3000 200 0 0 1004 102 2013 3 3000 200 300 0 1004 102 2013 4 3000 200 300 400 1004 102 2013 5 3000 200 300 400 Here the transformation rule is we need to pick the highest Seqnumber with respect to each ssn per year per Employerid and the amounts. i.e for 10004 for sum(q1taxamt) is 2000 +3000 = 5000 The Logic is ssn 101 has highest seq number of 4 and ssn 102 has highest seq number of 5 so we need to pick those values wrt to employerid Example: Want to check for q1taxamt: 2000 +3000 = 5000 Want to check for q4taxamt: 300 +400 = 700 output must be: Employerid YEAR q1taxamt q2taxamt q3taxamt q4taxamt 10004 2013 5000 300 500 700 The below query is generating wrong result: Select Sum(E1.q1taxamt) q1taxamt, Sum(E1.q2taxamt) q2taxamt, Sum(E1.q3taxamt) q3taxamt, Sum(E1.q4taxamt) q4taxamt, E1.Employerid, E1.YEAR from Employee E1 join ( select E.Employerid, MAX(E.seqnumber) seqnumber, E.YEAR from Employee E group by E.Employerid,E.SSn,E.year )E2 on E1.Employerid=E2.Employerid AND E1.YEAR=E2.YEAR and E1.seqnumber=E2.Taxseqnumber
Just use row_number(): select e.* from (select e.*, row_number() over (partition by E.Employerid, E.SSn, E.year order by e.seqnumber desc ) as seqnum from Employee e ) e where seqnum = 1; For best performance, you want an index on Employee(EmployerId, SSN, seqnumber desc).
You missing SSN join predicate between E1 and E2 thats why you are getting wrong result. I think this might be faster than Row_Number method. Select Sum(E1.q1taxamt) q1taxamt, Sum(E1.q2taxamt) q2taxamt, Sum(E1.q3taxamt) q3taxamt, Sum(E1.q4taxamt) q4taxamt, E1.Employerid, E1.YEAR from Employee E1 join ( select E.Employerid, E.SSn, MAX(E.seqnumber) seqnumber, E.YEAR from Employee E group by E.Employerid,E.SSn,E.year )E2 on E1.Employerid=E2.Employerid AND E1.YEAR=E2.YEAR AND E1.SSN = E2.SSN --Here and E1.seqnumber=E2.Taxseqnumber
SQL Group by range and total column
With the following function and stored procedure i get a resultset with 2 columns. What i need additional is a third column total for all open invoices inner score range It would great for any idea. ALTER FUNCTION dbo.OpenOrders ( #MandantId int ) RETURNS TABLE AS RETURN SELECT SUM(Invoices.Amount - ISNULL(Payment.Amount, 0)) AS Op FROM Invoices INNER JOIN Orders ON Invoices.OrderId = Orders.OrderId LEFT OUTER JOIN Payment ON Invoices.InvoiceId = Payment.InvoiceId WHERE (Orders.MandantId = #MandantId) GROUP BY Invoice.InvoiceId, Invoices.Amount HAVING (SUM(Invoices.Amount - ISNULL(Payment.Amount, 0)) <> 0) ALTER PROCEDURE dbo.GetOpRanges #MandantId int AS BEGIN SELECT * INTO #tmp_ranges FROM //wrong in first post -> OPDebitorByMandant(#MandantId) OpenOrders(#MandantId) SELECT op AS [score range], COUNT(*) AS [number of occurences] FROM (SELECT CASE WHEN op BETWEEN 0 AND 50 THEN ' 0- 50' WHEN op BETWEEN 50 AND 100 THEN ' 50-100' WHEN op BETWEEN 100 AND 500 THEN '100-500' ELSE '500 and >' END AS op FROM [#tmp_ranges]) AS t GROUP BY op RETURN Result: score range number of occurences range ------------------+------------- 0- 50 23 50-100 4 100-500 4 500 and > 21 What i need additional is a third column total for all open invoices inner score range. Target result: score range number of occurences Total -----------+--------------------+------ 0- 50 23 1.150 50-100 4 400 100-500 4 2.000 500 and > 21 22.000 Tables: Invoices InvoiceId CustomerId OrderId DateOfInvoice Amount ----------+----------+-------+-------------+------ 1 1 20 20160301 1000.00 2 2 22 20160501 2000.00 3 1 102 20160601 3000.00 ... Orders OrderId MandantId CustomerId DateOfOrder Amount -------+---------+----------+-----------+----------- 20 1 1 20160101 1000.00 22 1 2 20160101 2000.00 102 1 1 20160101 3000.00 ... Payment PaymentId MandantId CustomerId InvoiceId OrderId DateOfPayment Amount ---------+---------+----------+---------+-------+-------------+------------- 1 1 1 1 20 20160310 1000.00 2 1 2 2 22 20160505 2000.00 3 1 1 3 102 20160610 3000.00 ... hope it's helpfull and thanks again in advance for any solution
Multiple joins with aggregates
I have the two following tables: Person: EntityId FirstName LastName ----------- ------------------ ----------------- 1 Ion Ionel 2 Fane Fanel 3 George Georgel 4 Mircea Mircel SalesQuotaHistory SalesQuotaId EntityId SalesQuota SalesOrderDate ------------ ----------- ----------- ----------------------- 1 1 1000 2014-01-01 00:00:00.000 2 1 1000 2014-01-02 00:00:00.000 3 1 1000 2014-01-03 00:00:00.000 4 3 3000 2013-01-01 00:00:00.000 5 3 3000 2013-01-01 00:00:00.000 7 4 4000 2015-01-01 00:00:00.000 8 4 4000 2015-01-02 00:00:00.000 9 4 4000 2015-01-03 00:00:00.000 10 1 1000 2015-01-01 00:00:00.000 11 1 1000 2015-01-02 00:00:00.000 I am trying to get the SalesQuota for each user in 2014 and 2015. Using this query i am getting an erroneous result: SELECT p.EntityId , p.FirstName , SUM(sqh2014.SalesQuota) AS '2014' , SUM(sqh2015.SalesQuota) AS '2015' FROM Person p LEFT OUTER JOIN SalesQuotaHistory sqh2014 ON p.EntityId = sqh2014.EntityId AND YEAR(sqh2014.SalesOrderDate) = 2014 LEFT OUTER JOIN SalesQuotaHistory sqh2015 ON p.EntityId = sqh2015.EntityId AND YEAR(sqh2015.SalesOrderDate) = 2015 GROUP BY p.EntityId, p.FirstName EntityId FirstName 2014 2015 --------- ----------- ---------- -------------------- 1 Ion 6000 6000 2 Fane NULL NULL 3 George NULL NULL 4 Mircea NULL 12000 In fact, Id 1 has a total SalesQuota of 3000 in 2014 and 2000 in 2015. What i am asking here, is .. what is really happening behind the scenes? What is the order of operation in this specific case? Thanks to my last post i was able to solve this using the following query: SELECT p.EntityId , p.FirstName , SUM(CASE WHEN YEAR(sqh.SalesOrderDate) = 2014 THEN sqh.SalesQuota ELSE 0 END) AS '2014' , SUM(CASE WHEN YEAR(sqh.SalesOrderDate) = 2015 THEN sqh.SalesQuota ELSE 0 END) AS '2015' FROM Person p LEFT OUTER JOIN SalesQuotaHistory sqh ON p.EntityId = sqh.EntityId GROUP BY p.EntityId, p.FirstName EntityId FirstName 2014 2015 ----------- --------------------- ----------- ----------- 1 Ion 3000 2000 2 Fane 0 0 3 George 0 0 4 Mircea 0 12000 but without understanding what's wrong with the first attempt .. i can't get over this .. Any explanation would be greatly appreciated.
Is easy to see what is happening if you change your select to SELECT * and remove the group by You first approach need something like this Sql Fiddle Demo SELECT p.[EntityId] , p.FirstName , COALESCE(s2014,0) as [2014] , COALESCE(s2015,0) as [2015] FROM Person p LEFT JOIN (SELECT EntityId, SUM(SalesQuota) s2014 FROM SalesQuotaHistory WHERE YEAR(SalesOrderDate) = 2014 GROUP BY EntityId ) as s1 ON p.[EntityId] = s1.EntityId LEFT JOIN (SELECT EntityId, SUM(SalesQuota) s2015 FROM SalesQuotaHistory WHERE YEAR(SalesOrderDate) = 2015 GROUP BY EntityId ) as s2 ON p.[EntityId] = s2.EntityId Joining with the result data only if exist for that id and year. OUTPUT | EntityId | FirstName | 2014 | 2015 | |----------|-----------|------|-------| | 1 | Ion | 3000 | 2000 | | 2 | Fane | 0 | 0 | | 3 | George | 0 | 0 | | 4 | Mircea | 0 | 12000 |
You have multiple rows for each year, so the first method is producing a Cartesian product. For instance, consider EntityId 100: 1 1 1000 2014-01-01 00:00:00.000 2 1 1000 2014-01-02 00:00:00.000 3 1 1000 2014-01-03 00:00:00.000 10 1 1000 2015-01-01 00:00:00.000 11 1 1000 2015-01-02 00:00:00.000 The intermediate result from the join produces six rows, with these SalesQuotaId: 1 10 1 11 2 10 2 11 3 10 3 11 You can then do the math -- the result is off because of the multiple rows. You seem to know how to fix the problem. The conditional aggregation approach produces the correct answer.
You could improve the speed of your query by adding a WHERE condition to filter only the years over which you're looking for data: SELECT p.EntityId , p.FirstName , SUM(CASE WHEN YEAR(sqh.SalesOrderDate) = 2014 THEN sqh.SalesQuota ELSE 0 END) AS '2014' , SUM(CASE WHEN YEAR(sqh.SalesOrderDate) = 2015 THEN sqh.SalesQuota ELSE 0 END) AS '2015' FROM Person p LEFT OUTER JOIN SalesQuotaHistory sqh ON p.EntityId = sqh.EntityId WHERE YEAR(sqh.SalesOrderDate) IN (2014, 2015) GROUP BY p.EntityId, p.FirstName Otherwise, the query that you found is the way to go (good job!)
Oracle 10g unpivot returning values in one column and creating month column
We just found out that the new database we have been given access to is Oracle 10g, so we are unable to use fcn like UNPIVOT. We have a table like this.. SUBMISSION COUNTRY CPM_ID PFM_ID T_AREA CNTRY_CODE V_TYPE RES_CAT JAN_2014 FEB_2014 01-JUN-2014 USA 10 24 TEST1 USA V1 210 5 10 01-AUG-2014 UK 20 30 TEST2 UK V1 213 20 30 The desired output would look like this... SUBMISSION COUNTRY CPM_ID PFM_ID T_AREA CNTRY_CODE V_TYPE RES_CAT MONTH VALUE 01-JUN-2014 USA 10 24 TEST1 USA V1 210 01-JAN-2014 5 01-JUN-2014 USA 10 24 TEST1 USA V1 210 01-FEB-2014 10 01-AUG-2014 UK 20 30 TEST2 UK V1 213 01-JAN-2014 20 01-AUG-2014 UK 20 30 TEST2 UK V1 213 01-FEB-2014 30 I am working with a query like this...but I cannot get the month column to come out right... select * from (select t.submission, t.country, t.cpm_id, t.pfm_id, t.t_area, t.cntry_code, t.v_type, t.res_cat, (case when n.n = 1 then JAN-2014 when n.n = 1 then FEB-2014 end) as value from table1 t cross join (select FEB_2014 as n from dual union all select FEB_2014 from dual) n ) s where value is not null; Thanks for your help,
I would do: select t.submission, t.country, t.cpm_id, t.pfm_id, t.t_area, t.cntry_code, t.v_type, t.res_cat, n.d, case when n.d = '01-JAN-2014' then t.jan_2014 else t.feb_2014 end value from table1 t cross join ( select '01-JAN-2014' d from dual union all select '01-FEB-2014' d from dual ) n;