How to get correct cumulative balance? - sql

I have this simple query
select ArticleID, Prix, Qte, InfStock
, SUM(Qte*InfStock) OVER (Partition BY ArticleID ORDER BY DateDocument) AS CUMUL
FROM Balance
Please look the result (Line 4)
Here is the backup file(zipped)

You need to add to the end of the OVER clause ROWS UNBOUNDED PRECEDING.
SUM defaults to RANGE UNBOUNDED PRECEDING which can cause issues like this.
See here for example, for further explanation.

Related

how to use current row data in a condition inside a window function on a partition with range between unbounded preceding and current row

I need to use the current row values in a condition used in a window function on a partition with range. See my example query I am looking for.
select
count(case when orderdate >=
(**current_row.orderdate** -30) then 1 end)
over (partition by customerid order by orderdate range between unbounded preceding and current row)
from xyz
Not getting correct syntax.
Please see below example output required. This is just an example, the 30 days and the logic is just a sample.

Create a column with lagging running total

I have a table like below:
From values, I can easily get to cum_values using window function:
sum(values) over (order by id ASC rows between unbounded preceding and current row) as cum_values
How do I get cum_values_minus1, I tried a few iterations using "rows between", but they aren't working!
Any help is appreciated.

query Get Balances in Oracle table stock

i have sample data in oracle data table namely STOKREWARD table, i wanna get balance between quantity IN and quantity OUT.
i wanna get value BALANCES like this:
i try using query like this, but the result doesn't i want
SELECT STOKREWARD.NO, STOKREWARD.DODATE, STOKREWARD.REWARDNAME, STOKREWARD.NOTES,
STOKREWARD.QTYIN, STOKREWARD.QTYOUT,
(STOKREWARD.QTYIN- STOKREWARD.QTYOUT) AS BALANCES
FROM STOKREWARD
ORDER BY STOKREWARD.NO ASC
this query gives result:
anyone can help me? thanks
Using SUM() OVER:
SELECT NO, DODATE, CODE, REWARDNAME, NOTES, QTYIN, QTYOUT,
SUM (QTYIN - QTYOUT) OVER (ORDER BY DODATE ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS BALANCES
FROM STOKREWARD

how to use median as a analytic function (oracle SQL)

Can you explain why the following works:
select recdate,avg(logtime)
over
(ORDER BY recdate rows between 10 preceding and 0 following) as logtime
from v_download_times;
and the following doesn’t
select recdate,median(logtime)
over
(ORDER BY recdate rows between 10 preceding and 0 following) as logtime
from v_download_times;
(median instead of avg)
I get an ORA-30487 error.
and I would be grateful for a workaround.
The error message is ORA-30487: ORDER BY not allowed here. And sure enough, if we consult the documentation for the MEDIAN function it says:
"You can use MEDIAN as an analytic function. You can specify only the
query_partition_clause in its OVER clause."
But it is not redundant if you only want to take it from a certain number of rows preceding the current one.
A way around may be limiting your data set just for the median purpose, like
select
median(field) over (partition by field2)
from ( select * from dataset
where period_back between 0 and 2 )
MEDIAN doesn't allow an ORDER BY clause. As APC points out in his answer, the documentation tells us we can only specify the query_partition_clause.
ORDER BY is redundant as we're looking for the central value -- it's the same regardless of order.

SQL Server 2012 Windowing function to calculate a running total

I need some help with windowing functions.
I have been playing around with sql 2012 windowing functions recently. I know that you can calculate the sum within a window and the running total within a window. But i was wondering; is it possible to calculate the previous running total i.e. the running total not including the current row ? I assume you would need to use the ROW or RANGE argument and I know there is a CURRENT ROW option but I would need a CURRENT ROW - I which is invalid syntax. My knowledge of the ROW and RANGE arguments is limited so any help would be gratefully received.
I know that there are many solutions to this problem, but I am looking to understand the ROW, RANGE arguments and I assume the problem can be cracked with these. I have included one possible way to calculate the previous running total but I wonder if there is a better way.
USE AdventureWorks2012
SELECT s.SalesOrderID
, s.SalesOrderDetailID
, s.OrderQty
, SUM(s.OrderQty) OVER (PARTITION BY SalesOrderID) AS RunningTotal
, SUM(s.OrderQty) OVER (PARTITION BY SalesOrderID
ORDER BY SalesOrderDetailID) - s.OrderQty AS PreviousRunningTotal
-- Sudo code - I know this does not work
--, SUM(s.OrderQty) OVER (PARTITION BY SalesOrderID
-- ORDER BY SalesOrderDetailID
-- ROWS BETWEEN UNBOUNDED PRECEDING
-- AND CURRENT ROW - 1)
-- AS SudoCodePreviousRunningTotal
FROM Sales.SalesOrderDetail s
WHERE SalesOrderID IN (43670, 43669, 43667, 43663)
ORDER BY s.SalesOrderID
, s.SalesOrderDetailID
, s.OrderQty
Thanks in advance
You could subtract the current row's value:
SUM(s.OrderQty) OVER (PARTITION BY SalesOrderID
ORDER BY SalesOrderDetailID) - s.OrderQty
Or according to the syntax at MSDN and ypercube's answer:
<window frame preceding> ::=
{
UNBOUNDED PRECEDING
| <unsigned_value_specification> PRECEDING
| CURRENT ROW
}
-->
SUM(s.OrderQty) OVER (PARTITION BY SalesOrderID
ORDER BY SalesOrderDetailID
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING)