I have data like this:
Id Price Quantity Value
1 1000 4 4000
2 1000 4.5 4500
3 1000 5 5000
and I would ask for database row when the price is the sum of for example 2500.
I expected to answer this:
Id Price Quantity Value
1 1000 4 4000
2 1000 4.5 4500
3 500 5 2500
Of could I could use while loop but I think select will be more smart. My database is Firebird.
I have 3 lines in database for example buy dollars.
- first, I bought $ 1000 for 4 PLN,
- second I bought $ 1000 for 4.5 PLN,
- and the third I bought $ 1000 for 5 PLN.
(PLN is Polish currency).
And now I would like to sell $ 2500 and of course I would like know how much is dollars cost in PLN.
In my opinion this transaction cost: (1000 * 4) + (1000 * 4.5) + (500 * 5) = 12000 PLN.
This is very important to know how much dollars is cost in PLN to Polish accountant.
Here is example of Delphi code, Q is TQuery, other variables are Real. You should add correct rounding depending on law regulations in Poland.
The following shows the essentials of how to operate a FIFO model of dollar purchases and sales in SQL. I've written and tested it for MS SQL Server translated it into Firebird SQL and tested it
So, start with a DollarPurchases table as follows
and add a few rows to it
Then, we can create a view which includes a running total
The contents of the view would look like this
Now, suppose we want to sell a certain amount of dollars. An algorithm to do this might be as follows, assuming the ID column value reflects the order in which the purchases were made:
Find the lowest ID of a row whose
cumulativecost
exceeds the dollar amount to sell.Flag or delete all the rows with a lower ID, as they will need to be sold in their entirety to realise the dollar amount.
The dollars in the row with the found ID will need to be sold in whole or in part to realise the remainder of the dollar amount. If it needs to be the whole, delete or flag this row as per step 1, if in part, update the row to reflect the residual quantity of dollars and their cost.
and that's it.
In the following, instead of doing these operations on the live data, I'm going to make a copy of the DollarPurchases and perform the operations on that. I've left a few debugging statements in the code for checking purposes.
This yields
Of course, the above only addresses the case where the highest relevant row is only partially sold, but it would be trivial to deal with it as per step 1 if it is being sold in its entirety.
I imagine that a real SQL expert could do all the above in a single SQL statement, but I hope this step-by-step approach makes it easier to follow what's going on and to debug it.
It's worth mentioning that this could all be done processing the data row-by-row using a SQL cursor in a
while
loop, but maybe that's a bit too much like the Delphi code example you've been given in the other answer.A translation of the above into Firebird SQL is shown below. It has two main changes compared to the MS SQL Server version:
Ihe computed
cost
column is renamed toavalue
(it would have beenvalue
but for a naming conflict).As Firebird SQL does not support the free use of local variables in the way TransactSQL does, I replaced the variable by entries in a single-row
variables
table. This makes some of the statements a bit wordier but is preferable from my pov to doing it with Firebird'sEXECUTE BLOCK
.The code: