I have a table table1 which contains the details of any depositor like
Depositor
Deposit_Amount
Deposit_Date
Maturity_Date
Tenure
Rate
A
25000
2021-08-10
2022-08-10
12
10%
I have another table table2 which contains the interest due date as:
Interest_Due_Date
2021-09-30
2021-12-31
2022-03-31
2022-06-30
2022-08-10
My Code is:
with recursive recur (n, start_bal, days,principle,interest, end_bal) as
(
select sno,deposit_amount,rate,days,deposit_amount * (((rate::decimal(18,2))/100)/365)*days as interest, deposit_amount+(deposit_amount * (((rate::decimal(18,2))/100)/365)*days) as end_bal from (
SELECT
sno, COALESCE(DATE_PART('day', deposit_date::TIMESTAMP - lag(deposit_date::TIMESTAMP) over
(ORDER BY sno ASC rows BETWEEN UNBOUNDED PRECEDING AND CURRENT row)),0) AS
days, deposit_date, deposit_amount, rate
FROM
( SELECT
ROW_NUMBER () OVER (ORDER BY deposit_date) AS sno,
deposit_date,
deposit_amount,
rate
FROM
( SELECT
t1.deposit_date, t1.deposit_amount, t1.rate from table1 t1
UNION ALL
SELECT
t2.Interest_Due_Date AS idate, 0 as depo_amount, 0 as rate
FROM
table2 t2
ORDER BY
deposit_date) dep) calc) b where sno = 1 union all select b.sno, b.end_bal,b.days,b.prin_bal,(coalesce(a.end_bal,0)) * (((b.rate)/100)/365)*b.days as interest_NEW,
coalesce(a.end_bal,0)+ ((a.end_bal) * (((calc.rate)/100)/365)*calc.days) as end_bal_NEW
from b, recur as a
where calc.sno = a.n+1 ) select * from recur
"Every time when i try to execute the query its showing an error 'relation 'b' does not exist"
...
The result table should be
Deposit Amount
Date
Days
Interest
Total Amount
25000
2021-08-10
0
0
25000
0
2021-09-30
51
349.32
25349.32
0
2021-12-31
92
638.94
25988.26
0
2022-03-31
90
640.81
26629.06
0
2022-06-30
91
663.90
27292.97
0
2022-08-10
41
306.58
27599.54
I have a table with the following entries in them
id price quantity
1. 10 75
2. 10 75
3. 10 -150
4. 10 75
5. 10 -75
What I need to do is to update each row with a number that is the number of times the running total has been 0. In the above example, the cumulative totals would be
id. cum_total
1. 750
2. 1500
3. 0
4. 750
5. 0
Desired result
id price quantity seq
1. 10 75 1
2. 10 75 1
3. 10 -150 1
4. 10 75 2
5. 10 -75 2
I'm now lost in a spiral of CTEs and window functions and figured I'd ask the experts.
Thanks in advance :-)
Here is one option using analytic functions:
WITH cte AS (
SELECT *, CASE WHEN SUM(price*quantity) OVER (ORDER BY id) = 0 THEN 1 ELSE 0 END AS price_sum
FROM yourTable
),
cte2 AS (
SELECT *, LAG(price_sum, 1, 0) OVER (ORDER BY id) price_sum_lag
FROM cte
)
SELECT id, price, quantity, 1 + SUM(price_sum_lag) OVER (ORDER BY id) cumulative_total
FROM cte2
ORDER BY id;
Demo
You may try running each CTE in succession to see how the logic is working.
With window functions:
SELECT id, price, quantity,
coalesce(
sum(CASE WHEN iszero THEN 1 ELSE 0 END)
OVER (ORDER BY id
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING),
0
) + 1 AS batch
FROM (SELECT id, price, quantity,
sum(price * quantity) OVER (ORDER BY id) = 0 AS iszero
FROM mytable) AS subq;
i want to get sum of pivoted column values to new column and insert output records to a temporary table
select * from (select v.JobNo as JobNo,aj.VehicleNumber as VehicleNo,isnull(g.ImageCount,0) as ImageCount,s.ParamKey as ImageType from dbo.Visits v inner join (select VisitId as visit,paramkey,Value from dbo.VisitParams) s on s.visit = v.visitid left outer join ( select VisitId,FieldId, ( COUNT(*)) as ImageCount from dbo.vw_ImageGallery group by FieldId,VisitId) g on s.visit = g.VisitId and g.FieldId = s.ParamKey inner join Users u on u.UserId = v.CreatedBy inner join AssignedJobs aj on aj.CSRCode = u.Code and aj.JobNumber = v.JobNo where v.VisitType = 1 and v.TimeVisited >= '2019-03-01' AND v.TimeVisited <= '2019-04-01' )as a
PIVOT ( max([ImageCount]) FOR [ImageType] IN ([5],[20],[21]) ) as pvt order by [JobNo]
my actual out put is
job no vehicleno 1 2 5
---------------------------------------------------------
BL1052385 648792 0 8 0
BL1054161 CAT2410 2 8 0
BL1107290 NB 0134 0 5 0
BL1174714 GP 3784 1 7 3
i expect the output like
job no vehicleno 1 2 5 Total Count
----------------------------------------------------------
BL1052385 648792 0 8 0 8
BL1054161 CAT2410 2 8 0 10
BL1107290 NB 0134 0 5 0 5
BL1174714 GP 3784 1 7 3 11
I prefer using conditional aggregation rather than pivot. It is more flexible:
select v.JobNo, aj.VehicleNumber,
sum(case when vp.ParamKey = 1 then g.ImageCount else 0 end) as imagetype_1,
sum(case when vp.ParamKey = 20 then g.ImageCount else 0 end) as imagetype_20,
sum(case when vp.ParamKey = 21 then g.ImageCount else 0 end) as imagetype_21,
count(*) as total
from dbo.Visits v join
dbo.VisitParams vp
on vp.visit = v.visitid join
Users u
on u.UserId = v.CreatedBy join
AssignedJobs aj
on aj.CSRCode = u.Code and
aj.JobNumber = v.JobNo left outer join
(select VisitId, FieldId, count(*) as ImageCount
from dbo.vw_ImageGallery ig
group by FieldId, VisitId
) g
on vp.visit = g.VisitId and
g.FieldId = s.ParamKey
where v.VisitType = 1 and
v.TimeVisited >= '2019-03-01' and
v.TimeVisited <= '2019-04-01' and
vp.ParamKey in (5, 20, 21)
group by v.JobNo, aj.VehicleNumber;
order by v.JobNo
I have a stock transaction table like this:
StockID Item TransDate TranType BatchNo Qty Price
10001 ABC 01-Apr-2012 IN 71001000 200 750.0
10002 ABC 02-Apr-2012 OUT 100
10003 ABC 03-Apr-2012 IN 71001001 50 700.0
10004 ABC 04-Apr-2012 IN 71001002 75 800.0
10005 ABC 10-Apr-2012 OUT 125
10006 XYZ 05-Apr-2012 IN 71001003 150 350.0
10007 XYZ 05-Apr-2012 OUT 120
10008 XYZ 15-Apr-2012 OUT 10
10009 XYZ 20-Apr-2012 IN 71001004 90 340.0
10010 PQR 06-Apr-2012 IN 71001005 50 510.0
10011 PQR 15-Apr-2012 IN 71001006 60 505.0
10012 MNO 01-Apr-2012 IN 71001007 76 410.0
10013 MNO 11-Apr-2012 OUT 76
Each of my IN transactions has price associated to it and a batch number (lot number). Now I would like to calculate the remaining quantity by First In First Out (FIFO) rule, meaning the first in should be adjusted with first out. After adjusting the quantities the remaining balances are to be calculated against each IN transaction for the same item as shown below:
StockID Item TransDate TranType BatchNo Qty Price RemainingQty
10001 ABC 01-Apr-2012 IN 71001000 200 750.0 0
10002 ABC 02-Apr-2012 OUT 100
10003 ABC 03-Apr-2012 IN 71001001 50 700.0 25
10004 ABC 04-Apr-2012 IN 71001002 75 800.0 75
10005 ABC 10-Apr-2012 OUT 125
10006 XYZ 05-Apr-2012 IN 71001003 150 350.0 20
10007 XYZ 05-Apr-2012 OUT 120
10008 XYZ 15-Apr-2012 OUT 10
10009 XYZ 20-Apr-2012 IN 71001004 90 340.0 90
10010 PQR 06-Apr-2012 IN 71001005 50 510.0 50
10011 PQR 15-Apr-2012 IN 71001006 60 505.0 60
10012 MNO 01-Apr-2012 IN 71001007 76 410.0 0
10013 MNO 11-Apr-2012 OUT 76
As we can see from the above table for item ABC, after adjusting (125 + 100) OUT qty against the IN qty (100 + 50 + 75) using FIFO the quantity remaining for the batch 71001000 is 0, 71001001 is 25 and for batch 71001002 is 75. From the remaining quantity the value can be derived.
Please help me to achieve this using any of the methods (either cursor based or CTE or JOINS, etc)
Thanks in advance for the help.
One of the users of StockOverflow suggested this answer:
SELECT 10001 as stockid,'ABC' as item,'01-Apr-2012' as transdate,'IN' as trantype, 71001000 as batchno, 200 as qty, 750.0 as price INTO #sample
UNION ALL SELECT 10002 ,'ABC','02-Apr-2012','OUT', NULL ,100,NULL
UNION ALL SELECT 10003 ,'ABC','03-Apr-2012','IN', 71001001, 50 , 700.0
UNION ALL SELECT 10004 ,'ABC','04-Apr-2012','IN', 71001002, 75 , 800.0
UNION ALL SELECT 10005 ,'ABC','10-Apr-2012','OUT', NULL ,125,NULL
UNION ALL SELECT 10006 ,'XYZ','05-Apr-2012','IN', 71001003, 150 , 350.0
UNION ALL SELECT 10007 ,'XYZ','05-Apr-2012','OUT', NULL , 120 ,NULL
UNION ALL SELECT 10008 ,'XYZ','15-Apr-2012','OUT', NULL , 10 ,NULL
UNION ALL SELECT 10009 ,'XYZ','20-Apr-2012','IN', 71001004, 90 , 340.0
UNION ALL SELECT 10010 ,'PQR','06-Apr-2012','IN', 71001005, 50 , 510.0
UNION ALL SELECT 10011 ,'PQR','15-Apr-2012','IN', 71001006, 60 , 505.0
UNION ALL SELECT 10012 ,'MNO','01-Apr-2012','IN', 71001007, 76 , 410.0
UNION ALL SELECT 10013 ,'MNO','11-Apr-2012','OUT', NULL ,76 ,NULL
;WITH remaining AS
(
SELECT *,
CASE
WHEN trantype = 'IN' THEN 1
ELSE -1
END * qty AS stock_shift,
ROW_NUMBER() OVER(PARTITION BY item ORDER BY transdate) AS row,
CASE
WHEN trantype = 'OUT' THEN NULL
ELSE ROW_NUMBER()OVER(PARTITION BY item, CASE WHEN trantype = 'IN' THEN 0 ELSE 1 END ORDER BY transdate)
END AS in_row,
SUM(CASE WHEN trantype = 'OUT' THEN qty END) OVER(PARTITION BY item) AS total_out
FROM #sample
)
,remaining2 AS
(
SELECT r1.item,
r1.stockid,
MAX(r1.transdate) AS transdate,
MAX(r1.trantype) AS trantype,
MAX(r1.batchno) AS batchno,
MAX(r1.qty) AS qty,
MAX(r1.price) AS price,
MAX(r1.total_out) AS total_out,
MAX(r1.in_row) AS in_row,
CASE
WHEN MAX(r1.trantype) = 'OUT' THEN NULL
WHEN SUM(CASE WHEN r1.trantype = 'IN' THEN r2.qty ELSE 0 END) - MAX(r1.total_out) < 0 THEN SUM(CASE WHEN r1.trantype = 'IN' THEN r2.qty ELSE 0 END)
- MAX(r1.total_out)
ELSE 0
END AS running_in
FROM remaining r1
LEFT OUTER JOIN remaining r2
ON r2.row <= r1.row
AND r2.item = r1.item
GROUP BY
r1.item,
r1.stockid
)
SELECT r2.item,
r2.stockid,
MAX(r2.transdate) AS transdate,
MAX(r2.trantype) AS trantype,
MAX(r2.batchno) AS batchno,
MAX(r2.qty) AS qty,
MAX(r2.price) AS price,
MAX(CASE WHEN r2.trantype = 'OUT' THEN NULL ELSE ISNULL(r2.qty + r3.running_in, 0) END) AS remaining_stock
FROM remaining2 r2
LEFT OUTER JOIN remaining2 r3
ON r2.in_row - 1 = r3.in_row
AND r2.item = r3.item
GROUP BY
r2.item,
r2.stockid
This sql is having a problem and the result is attached here The records for which the value are not matching are indicated in yellow color. Kindly help to solve the problem.
I think this should do the trick?
SELECT 10001 as stockid,'ABC' as item,'01-Apr-2012' as transdate,'IN' as trantype, 71001000 as batchno, 200 as qty, 750.0 as price INTO #sample
UNION ALL SELECT 10002 ,'ABC','02-Apr-2012','OUT', NULL ,100,NULL
UNION ALL SELECT 10003 ,'ABC','03-Apr-2012','IN', 71001001, 50 , 700.0
UNION ALL SELECT 10004 ,'ABC','04-Apr-2012','IN', 71001002, 75 , 800.0
UNION ALL SELECT 10005 ,'ABC','10-Apr-2012','OUT', NULL ,125,NULL
UNION ALL SELECT 10006 ,'XYZ','05-Apr-2012','IN', 71001003, 150 , 350.0
UNION ALL SELECT 10007 ,'XYZ','05-Apr-2012','OUT', NULL , 120 ,NULL
UNION ALL SELECT 10008 ,'XYZ','15-Apr-2012','OUT', NULL , 10 ,NULL
UNION ALL SELECT 10009 ,'XYZ','20-Apr-2012','IN', 71001004, 90 , 340.0
UNION ALL SELECT 10010 ,'PQR','06-Apr-2012','IN', 71001005, 50 , 510.0
UNION ALL SELECT 10011 ,'PQR','15-Apr-2012','IN', 71001006, 60 , 505.0
UNION ALL SELECT 10012 ,'MNO','01-Apr-2012','IN', 71001007, 76 , 410.0
UNION ALL SELECT 10013,'MNO','11-Apr-2012','OUT', NULL ,76 ,NULL
;with remaining_stock as
(
SELECT *
,CASE WHEN trantype = 'IN' THEN 1 ELSE -1 END * qty AS stock_shift
,row_number() OVER (PARTITION BY item ORDER BY transdate) as row
,CASE WHEN trantype = 'OUT' THEN NULL ELSE
row_number()OVER (PARTITION BY item,CASE WHEN trantype = 'IN' THEN 0 ELSE 1 END ORDER BY transdate) END as in_row
,CASE WHEN trantype = 'IN' THEN NULL ELSE
row_number()OVER (PARTITION BY item,CASE WHEN trantype = 'OUT' THEN 0 ELSE 1 END ORDER BY transdate) END as out_row
,ISNULL(SUM(CASE WHEN trantype = 'OUT' THEN qty END) OVER (PARTITION BY item),0) AS total_out
,ISNULL(SUM(CASE WHEN trantype = 'IN' THEN qty END) OVER (PARTITION BY item),0) AS total_in
FROM #sample
)
,remaining_stock2 AS
(
SELECT
r1.item
,r1.stockid
,MAX(r1.transdate) as transdate
,MAX(r1.trantype) as trantype
,MAX(r1.batchno) as batchno
,MAX(r1.qty) as qty
,MAX(r1.price) as price
,MAX(r1.total_in) as total_in
,MAX(r1.total_out) as total_out
,SUM(r2.qty) as running_in
FROM remaining_stock r1
LEFT OUTER JOIN remaining_stock r2 on r2.in_row <= r1.in_row
AND r2.item = r1.item
GROUP BY
r1.item
,r1.stockid
)
SELECT
item
,stockid
,transdate
,trantype
,batchno
,qty
,price
,CASE WHEN trantype = 'OUT' THEN NULL
WHEN total_out >= running_in THEN 0
WHEN (running_in - total_out) < qty THEN (running_in - total_out)
WHEN (running_in - total_out) >= qty THEN qty
END as remaining_stocks
FROM remaining_stock2
Your question isn't very clear to me on how the FIFO logic is to be applied. I'm going to assume that you want to associate each IN record against the next OUT record if one exists. To achieve this you need to join the table on itself like the following
select
t1.BatchNo,
isnull(t1.Qty,0) as 'IN Qty',
isnull(t2.Qty,0) as 'OUT Qty',
isnull(t1.Qty,0) - isnull(t2.Qty,0) as 'Remaining Qty'
from
tbl_test t1
left join tbl_test t2
on t2.StockID = (t1.StockID + 1)
and t2.TranType = 'OUT'
where
t1.TranType = 'IN'
The results will show you the following for the first 5 records for ABC from your question.
BatchNo | IN Qty | OUT Qty | Remaining Qty
71001000 | 200 | 100 | 100
71001001 | 50 | 0 | 50
71001002 | 75 | 125 | -50
The left join works on the assumption that the StockID for each IN record is always one less number than the associated OUT record. I personally think your data model needs improving.
OUT records should have a BatchNo assigned or a reference to the
StockID of the associated IN record
add a timestamp field for sequential ordering
add a DateTime field for handling IN/OUT occuring on same day