Oracle SQL Query one row with monthly value only, but need to group it by month - sql

I can't figure out the correct query on Oracle SQL
I have the following data:
Name Monthly_amount Start_date
Bob 100 April 2014
Mike 120 June 2014
Steve 80 Sept 2014
Bob 50 Dec 2014
And I would like to get the following result
Name |Jan-14| Feb-14| Mar-14| Apr-14 |May-14| Jun-14| Jul-14 |Aug-14|Sep-14|Oct-14| Nov-14| Dec-14
Bob 0 0 0 100 100 100 100 100 100 100 100 150
Mike 0 0 0 0 0 120 120 120 120 120 120 120
Steve 0 0 0 0 0 0 0 0 80 80 80 80

Something along the lines of this should work for you. If you need the column definitions to be dynamic, you would have to create it dynamically, but it's better to do that kind of things in your application.
SELECT Name,
SUM(CASE WHEN Start_date <= TO_DATE('01-JAN-2014','DD-MON-YYYY')
THEN Monthly_Amount ELSE 0 END) AS Jan14,
SUM(CASE WHEN Start_date <= TO_DATE('01-FEB-2014','DD-MON-YYYY')
THEN Monthly_Amount ELSE 0 END) AS Feb14,
(etc.)
FROM table1
GROUP BY Name;
(This assumes Name uniquely defines a person)

Related

sql split yearly record into 12 monthly records

I am trying to use common table expression to split an yearly record into 12 monthly records. I have to do it for next 20 years records . That means 20 rows into 600 rows (20*12=600 records).
What is the best way to do it. Can anyone help with an efficient way to do it.
Using a single table as shown below. Year 0 means current year so it should split into remaining months and year=1 means next year onward it should split into 12 (months) records
id year value
1 0 3155174.87
1 1 30423037.3
1 2 35339631.25
expected result should look like this:
Id Year Month Value Calender year
1 0 5 150 2022
1 0 6 150 2022
1 0 7 150 2022
1 0 8 150 2022
1 0 9 150 2022
1 0 10 150 2022
1 0 11 150 2022
1 0 12 150 2022
1 0 1 150 2023
1 0 2 150 2023
1 0 3 150 2023
1 0 4 150 2023
1 1 5 100 2023
1 1 6 100 2023
1 1 7 100 2023
1 1 8 100 2023
1 1 9 100 2023
1 1 10 100 2023
1 1 11 100 2023
1 1 12 100 2023
1 1 1 100 2024
1 1 2 100 2024
1 1 3 100 2024
1 1 4 100 2024
You can simply join onto a list of months, and then use a bit of arithmetic to split the Value
SELECT
t.Id,
t.Year,
v.Month,
Value = t.Value / CASE WHEN t.Year = 0 THEN 13 - MONTH(GETDATE()) ELSE 12 END
FROM YourTable t
JOIN (VALUES
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)
) v(Month) ON t.year > 0 OR v.Month >= MONTH(GETDATE());
db<>fiddle

SSRS REPORT SQL

I have data as below
Year Period Country STATUS COST1 COST2 TOTAL COST
2019 1 Australia PERM 100 200 300
2019 2 NZ PERM 200 200 400
2019 3 ASIA TEMP 400 200 600
2019 4 NZ TEMP 500 200 700
I like to show in the SSRS report
I need period on COLUMN and STATUS in ROWS like below and total cost in data section
Period
1 2 3 4
+PERM TOTAL COST
+TEMP
And when end user toggle on + it will show more detail. But otherwise just like that.
Year Country COST1 COST2 TOTAL COST
PERM 2019 1 Australia 100 200 300
2019 2 NZ 200 200 400
TEMP 2019 3 ASIA 400 200 600
2019 4 NZ 500 200 700
thanks in advance
You seem to want conditional aggregation:
select status,
sum(case when period = 1 then total_cost else 0 end) as total_cost_1,
sum(case when period = 2 then total_cost else 0 end) as total_cost_2,
sum(case when period = 3 then total_cost else 0 end) as total_cost_3,
sum(case when period = 4 then total_cost else 0 end) as total_cost_4
from t
group by status;
With a Matrix in SSRS you can set the row groups to be based on the Period and Status without having to add an additional dataset.
Use Period for the Column Grouping so the field will expand to 4 columns based on the Period values.
Result:
This way you can have the detail below in the same table and hide it until the user toggles it.

proc sql statement to sum on values/rows that match a condition

I have a data table like below:
Table 1:
ROWID PERSONID YEAR pidDifference TIMETOEVENT DAYSBETVISIT
10 111 2009 . 100 .
110 120 2009 9 10 .
231 120 2009 0 20 10
222 120 2010 0 40 20
221 222 2009 102 10 30
321 222 2009 0 30 20
213 222 2009 0 10 20
432 321 2009 99 10 0
211 432 2009 111 20 10
212 432 2009 0 20 0
I want to sum over the DAYSBETVISIT column only when the pidDifference value is 0 for each PERSONID. So I wrote the following proc sql statement.
proc sql;
create table table5 as
(
select rowid, YEAR, PERSONID, pidDifference, TIMETOEVENT, DAYSBETVISIT,
SUM(CASE WHEN PIDDifference = 0 THEN DaysBetVisit ELSE 0 END)
from WORK.Table4_1
group by PERSONID,TIMETOEVENT, YEAR
);
quit;
However, the result I got was not summing the DAYSBETVISIT values in rows where PIDDifference = 0 within the same PERSONID. It just output the same value as was present in DAYSBETVISIT in that specific row.
Column that I NEED (sumdays) but don't get with above statement (showing the resultant column using above statement as OUT:
ROWID PERSONID YEAR pidDifference TIMETOEVENT DAYSBETVISIT sumdays OUT
10 111 2009 . 100 . 0 0
110 120 2009 9 10 . 0 0
231 120 2009 0 20 10 30 10
222 120 2010 0 40 20 30 20
221 222 2009 102 10 30 0 0
321 222 2009 0 30 20 40 20
213 222 2009 0 10 20 40 20
432 321 2009 99 10 0 0 0
211 432 2009 111 20 10 0 0
212 432 2009 0 20 0 0 0
I do not know what I am doing wrong.
I am using SAS EG Version 7.15, Base SAS version 9.4.
For your example data it looks like you just need to use two CASE statements. One to define which values to SUM() and another to define whether to report the SUM or not.
proc sql ;
select personid, piddifference, daysbetvisit, sumdays
, case when piddifference = 0
then sum(case when piddifference=0 then daysbetvisit else 0 end)
else 0 end as WANT
from expect
group by personid
;
quit;
Results
pid
PERSONID Difference DAYSBETVISIT sumdays WANT
--------------------------------------------------------
111 . . 0 0
120 0 10 30 30
120 0 20 30 30
120 9 . 0 0
222 0 20 40 40
222 0 20 40 40
222 102 30 0 0
321 99 0 0 0
432 0 0 0 0
432 111 10 0 0
SAS proc sql doesn't support window functions. I find the re-merging aggregations to be a bit difficult to use, except in the obvious cases. So, use a subquery or join and group by:
proc sql;
create table table5 as
select t.rowid, t.YEAR, t.PERSONID, t.pidDifference, t.TIMETOEVENT, t.DAYSBETVISIT,
tt.sum_DaysBetVisit
from WORK.Table4_1 t left join
(select personid, sum(DaysBetVisit) as sum_DaysBetVisit
from WORK.Table4_1
group by personid
having min(pidDifference) = max(pidDifference) and min(pidDifference) = 0
) tt
on tt.personid = t.personid;
Note: This doesn't handle NULL values for pidDifference. If that is a concern, you can add count(pidDifference) = count(*) to the having clause.

SQL query to update a column via phpmyadmin

I have a large 'scores' table that resembles the following:
quizid userid score high_score
1 john 50 0
1 bob 60 0
1 bob 65 0
1 steve 40 0
2 bob 20 0
2 bob 30 0
2 bob 15 0
current the 'high_score' column is '0' as it was just added. what I need to do is make a simple query to flag this column with a '1' for every instance where a user's score for each quiz is the highest one that user has for that quiz - i.e. after running the query I should have this:
quizid userid score high_score
1 john 50 1
1 bob 60 0
1 bob 65 1
1 steve 40 1
2 bob 20 0
2 bob 30 1
2 bob 15 0
Any help would be appreciated!
i'm not sure and i have not tested below code but try it maybe it help you
update scores set high_score=1 where (quizid,userid,score) in
(select quizid,userid,max(score) from scores group by quizid,userid)

Filter SQL query results by aggregrate

I need a query that shows the JobIDs where the Worker has not been paid BUT where the Company has been paid. Below are the table columns and sample data:
tblInvoices columns:
-------------------
JobID
InvoiceID
WorkerPaidAmountTotal
CompanyPaidAmountTotal
Sample data
-----------
JobID | InvoiceID | WorkerPaidAmountTotal | CompanyPaidAmountTotal
1 30 100 150
1 31 0 100
2 32 0 75
3 33 25 50
3 34 10 30
4 35 0 0
I know how to get the SUM of the amounts paid to either a Worker or the Company. The results look like this:
JobID Worker Company
1 100 250
2 0 75
3 35 80
4 0 0
But what I need are the results of just the JobIDs where the Worker has got 0 and the company >0. The results I want should be this, but I can't figure out the query to do so:
JobID Worker Company
2 0 75
Use HAVING clause to filter the groups. Try this :
SELECT jobid,
Worker=Sum(WorkerPaidAmountTotal),
Company=Sum(CompanyPaidAmountTotal)
FROM tablename
GROUP BY jobid
HAVING Sum(WorkerPaidAmountTotal) = 0
AND Sum(CompanyPaidAmountTotal) > 0
select jobid, worker, company where WorkerPaidAmountTotal = 0 and CompanyPaidAmountTotal
Seems to plain to do it... may be i did'nt understand the question