SQL first value by group - sql

In a table like this
acc_id time approved_amount balance
11 Jan14 580 500
11 Feb14 580 400
11 Mar14 580 300
11 Apr14 580 200
22 Jan14 . 800
22 Feb14 . 700
22 Mar14 . 600
I want to create a column orig_amount that would be equal to approved_amount if this is not null and to the first value of balance - to balance at time = min(time) by acc_id if approved_amount is null.
Therefore the desired output would look like this:
acc_id time approved_amount balance orig_amount
11 Jan14 580 500 580
11 Feb14 580 400 580
11 Mar14 580 300 580
11 Apr14 580 200 580
22 Jan14 . 800 800
22 Feb14 . 700 800
22 Mar14 . 600 800
I have now this
create table second_table as
select *,
coalesce(approved_amount, case when time = min(time) then
balance end ) as orig_amount
from first_table
group by acc_id
order by acc_id, time;
But still not the desired result. Can anybody help please?

You can use the first_value() window function and coalesce().
SELECT acc_id,
time,
approved_amount,
balance,
coalesce(approved_amount,
first_value(balance) OVER (PARTITION BY acc_id
ORDER BY time)) orig_amount
FROM first_table;
db<>fiddle

Related

How can I transfer the data from on column to another based on another column values in SQL

select Products, Fiscal_year, Fiscal_Period, Stock_QTY, DaysRemaining,
(Stock_QTY / DaysRemaining) as QtyforPeriod,
Stock_QTY -(Stock_QTY / DaysRemaining) as LeftforNextmonth
from Stocks
products| Fiscal_yaer| Fiscal_period| Stock_QTY |DaysReamain| QtyforPeriod |LeftforNextMonth
5000 22 1 100 4
6000 22 1 200 4
7000 22 2 300 20
7000 22 3 400 40
8000 23 1 500 60
5000 23 1 600 60
7000 23 2 700 90
8000 23 3 800 100
There is any possibility to write a query if the Fiscal_yae =22 Fiscal_period=4. Subtract StockTY - LeftforNextMonth of period 3 and divided by DaysRemaining.
Like if the Fiscal_yae =22 Fiscal_period=5. Subtract StockTY - LeftforNextMonth of period 4 and divided by days remaining.
Like if the Fiscal_yae =22 Fiscal_period=6. Subtract StockTY ( - ) LeftforNextMonth of period 5 and divided by days remaining.

SQL oracle SUM function with conditions

I have a table that looks like this
TIMECODE UNIT_CODE Department Account AMOUNT
20194 10 1000 1000 100
20194 10 2354 1100 150
20194 10 1000 1000 200
20194 10 2354 1000 100
20194 20 500 1000 250
20194 20 500 1100 200
How I need the results to be is like this
TIMECODE UNIT_CODE Department 1000 1100
20194 10 1000 300 NULL
20194 10 2354 100 150
20194 20 500 250 200
hopefully that gives you a better image, but basically I would need to do a SUM depending on the distinct value of the other columns. The accounts that were previously in rows would be changed into columns.
any ideas or help with this would be greatly appreciated
Try the following, here is the demo.
select
TIMECODE,
UNIT_CODE,
Department,
sum(case when Account = 1000 then AMOUNT end) as "1000",
sum(case when Account = 1100 then AMOUNT end) as "1100"
from myTable
group by
TIMECODE,
UNIT_CODE,
Department
Output:
---------------------------------------------------
| TIMECODE UNIT_CODE DEPARTMENT 1000 1100 |
---------------------------------------------------
| 20194 20 500 250 200 |
| 20194 10 1000 300 null|
| 20194 10 2354 100 150 |
---------------------------------------------------

Create a view on multiple row conditions

I have a Cycles table like this:
Value Name Month
10 P00006 201412
20 P00006 201501
30 P00006 201502
100 P00007 201509
200 P00007 201510
300 P00007 201511
I would like to create a view based on this table where for each Name I sum the values of the previous months.
This the expected result :
AccruedValue Name Month
10 P00006 201412
30 P00006 201501
60 P00006 201502
100 P00007 201509
300 P00007 201510
600 P00007 201511
I am not sure this can be achieved without a using a cursor so any help will be appreciated.
Test data:
create table cycles
(value NUMBER, name VARCHAR2(250), month VARCHAR2(250));
/
INSERT INTO cycles VALUES(10 , 'P00006','201412');
INSERT INTO cycles VALUES(20 , 'P00006','201501');
INSERT INTO cycles VALUES(30 , 'P00006','201502');
INSERT INTO cycles VALUES(100 , 'P00007','201509');
INSERT INTO cycles VALUES(200 , 'P00007','201510');
INSERT INTO cycles VALUES(300 , 'P00007','201511');
View my_view:
create or replace view my_view as
select
sum(value) over (partition by name order by month ) as AccruedValue ,
name ,
month
from cycles;
Result:
select * from v;
10 P00006 201412
30 P00006 201501
60 P00006 201502
100 P00007 201509
300 P00007 201510
600 P00007 201511

Calculate fixed Cost/day for multiple services on same date

Desired Output table T with Calculated Cost column:
SvcID Code ID Date Mins Units Cost
1 3000 15 4/4/2016 60 10 70
2 3000 17 4/4/2016 45 10 0
3 3000 15 5/2/2016 30 10 70
4 3000 18 5/2/2016 60 10 0
5 3000 10 5/2/2016 30 10 0
6 4200 16 2/1/2016 60 4 60
7 4200 9 2/1/2016 30 2 30
Query for calculating and displaying:
SELECT
...
,CASE
WHEN Code=4200 THEN Units*15
WHEN Code=3000 THEN ?
END AS Cost
FROM ...
WHERE Code IN ('3000','4200')
GROUP BY ....;
Cost should be a total of 70 for all services offered on same date for Code 3000, irrespective of number of services offered. No relation between Minutes and Units for this Code for calculating Cost.
One way could be to calculate cost as 70 for any one service and make the remaining services cost 0 for same date. Can this be done in the CASE statement?
Any better way to achieve this?
You need to Investigate Window functions MSDN.
Your case would become something like this:
-- New select statament
SELECT
...
,CASE
WHEN Code=4200 THEN Units*15
WHEN Code=3000 THEN ( CASE WHEN DuplicateNum = 1 THEN 70 ELSE 0 END )?
END AS Cost
FROM(
-- Your current query (with case statement removed) and ROW_NUMBER() function added
SELECT
..., ROW_NUMBER() OVER( PARTITION BY Code, Date ORDER BY ID ) AS DuplicateNum
FROM ...
WHERE Code IN ('3000','4200')
GROUP BY ....
) AS YourCurrentQuery;

Select for take opening balance for last date of month and sum of other amount in whole month

I have table balance_detail
sales_period sales_date opening_amt sales_amt payment_amt closing_amt
-----------------------------------------------------------------------------
201501 01-01-2015 210 100 110
201501 02-01-2015 110 300 280 130
201501 03-01-2015 130 50 80
201501 05-01-2015 80 600 670 10
201502 02-02-2015 10 160 100 70
201502 15-02-2015 70 100 170 0
And Want result like this
sales_period opening_amt sales_amt payment_amt closing_amt
-----------------------------------------------------------------------------
201501 80 1110 1110 10
201502 70 260 270 0
One method is to use conditional aggregation along with row_number():
select sales_period,
max(case when seqnum = 1 then opening_amt end) as opening_amt,
sum(sales_amt) as sales_amt,
sum(payment_amt) as payment_amt,
max(case when seqnum = 1 then closing_amt end) as closing_amt
from (select bd.*,
row_number() over (partition by sales_period order sales_date desc) as seqnum
from balance_detail bd
) bd
group by sales_period;