Running Total by Group SQL (Oracle)
Ah, I think I have figured it out.
select a.*, sum(Amount) over (partition by Location, Product order by Date) as Running_Amt
from Example_Table a
Oracle SQL - Running Sum based on group by and condition
You could make a first window sum()
to define the groups, then use it as partition for the outer query:
select
t.*,
sum(count1) over(partition by id, grp order by seq) running_count
from (
select
t.*,
sum(label) over(partition by id order by seq desc) grp
from mytable t
) t
Demo on DB Fiddle:
ID | SEQ | LABEL | COUNT1 | GRP | RUNNING_COUNT
-: | --: | ----: | -----: | --: | ------------:
1 | 1 | 0 | 3 | 1 | 3
1 | 2 | 0 | 2 | 1 | 5
1 | 3 | 0 | 6 | 1 | 11
1 | 4 | 1 | 2 | 1 | 13
1 | 5 | 0 | 3 | 0 | 3
1 | 6 | 0 | 5 | 0 | 8
2 | 1 | 0 | 2 | 1 | 2
2 | 2 | 1 | 1 | 1 | 3
2 | 3 | 0 | 3 | 0 | 3
How to get running total in Oracle using SUM and OVER
By default analytic functions use a RANGE windowing directive (see below - the default is the first version). What you are looking for is a ROWS directive (see below), which is not the default so you must include it explicitly.
The RANGE windowing clause (default) does exactly what you noticed: it treats all "tied" rows as "included in the sum".
ADDED: Link to documentation https://docs.oracle.com/cd/E11882_01/server.112/e41084/functions004.htm#i97640
with test_data ( x ) as (
select 10 from dual union all
select 20 from dual union all
select 30 from dual union all
select 30 from dual union all
select 30 from dual union all
select 100 from dual
)
select x
, sum(x) over (order by x range between unbounded preceding and current row) range_sum
, sum(x) over (order by x rows between unbounded preceding and current row) rows_sum
from test_data
order by x;
X RANGE_SUM ROWS_SUM
---------- ---------- ----------
10 10 10
20 30 30
30 120 60
30 120 90
30 120 120
100 220 220
Oracle SQL - trying to calculate running total with Group By without having an existing numerical column to sum
If a given product is never ordered twice on the same data, you can just use a window count:
select
t.*,
count(*) over(partition by reference order by date_ordered) running_count
from mytable t
If there are duplicates, then you need aggregation:
select
reference,
date_ordered,
sum(count(*)) over(partition by reference order by date_ordered) running_count
from mytable
group by reference, date_ordered
Finally: if you want to generate all combinations of dates and product, with the associated runnig count, then you would do:
select
r.reference,
d.date_ordered,
sum(count(t.reference)) over(partition by r.reference order by d.date_ordered) running_count
from (select distinct date_ordered from mytable) d
cross join (select distinct reference from mytable) r
left join mytable t
on t.date_ordered = d.date_ordered and t.reference = r.reference
group by d.date_ordered, r.reference
Running total by grouped records in table
Do you really need the extra table?
You can get that data you need with a simple query, which you can obviously create as a view if you want it to appear like a table.
This will get you the data you are looking for:
select
account, bookdate, amount,
sum(amount) over (partition by account order by bookdate) running_total
from t
/
This will create a view to show you the data as if it were a table:
create or replace view t2
as
select
account, bookdate, amount,
sum(amount) over (partition by account order by bookdate) running_total
from t
/
If you really need the table, do you mean that you need it constantly updated? or just a one off? Obviously if it's a one off you can just "create table as select" using the above query.
Test data I used is:
create table t(account number, bookdate date, amount number);
insert into t(account, bookdate, amount) values (1, to_date('20080101', 'yyyymmdd'), 100);
insert into t(account, bookdate, amount) values (1, to_date('20080102', 'yyyymmdd'), 101);
insert into t(account, bookdate, amount) values (1, to_date('20080103', 'yyyymmdd'), -200);
insert into t(account, bookdate, amount) values (2, to_date('20080102', 'yyyymmdd'), 200);
commit;
edit:
forgot to add; you specified that you wanted the table to be ordered - this doesn't really make sense, and makes me think that you really mean that you wanted the query/view - ordering is a result of the query you execute, not something that's inherant in the table (ignoring Index Organised Tables and the like).
Running total count with group by; SQL
Use window functions:
SELECT EXTRACT(year FROM HIRE_DATE) "Year", COUNT(*),
SUM(COUNT(*)) OVER (ORDER BY MIN(HIRE_DATE)) as running_count
FROM hr.Employees
GROUP BY EXTRACT(year FROM HIRE_DATE)
ORDER BY "Year" DESC;
Running total with subgroups
You're close, but your current query is doing the SUM
over all rows in each group. You just need to add a row specification for your cumulative sum:
Sum(sales-returns) over(
partition by Version, Country
Order by Week
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW -- all rows including current row
) Running_stock
TD Manual
Running total over repeating group by items based on time in Oracle SQL
In order to get the sums you are looking for you need a way to group the values you are interested in. You can generate a grouping ID by using the a couple of ROW_NUMBER
analytic functions, one partitioned by the key value. However due to your need to duplicate the KEY
column values this will need to be done in a couple of stages:
WITH t1 AS (
SELECT dta.*
, last_value(KEY IGNORE NULLS) -- Fill in the missing
OVER (ORDER BY TIME ASC) key2 -- key values
FROM your_data dta
), t2 AS (
SELECT t1.*
, row_number() OVER (ORDER BY TIME) -- Generate a
- row_number() OVER (PARTITION BY key2 -- grouping ID
ORDER BY TIME) gp
FROM t1
)
SELECT t2.*
, sum(amt) OVER (PARTITION BY gp, key2
ORDER BY TIME) running_sums
FROM t2;
The above query creates a running sum of AMT that restarts every time the key value changes. Whereas the following query used in place of the last select statement above gives the requested results, which I wouldn't term a running sum.
SELECT key2
, MIN(TIME) start_time
, MAX(TIME) stop_time
, sum(amt) amt
FROM t2
GROUP BY key2, gp;
To see the full time values you may want to either alter your session NLS_DATE_FORMAT
as below:
ALTER SESSION SET NLS_DATE_FORMAT='DD-MM-RRRR HH24:MI:SS';
Or wrap each date column in a TO_CHAR
function for output purposes.
running sum on group by
In Oracle, a running sum is easily done with the sum() ... over()
window function:
select name
, other_name
, name_count
, sum(name_count) over(
order by name, other_name) as running
from (
select name
, other_name
, count(name) as name_count
from ethnicity
group by
name
, other_name
order by
name
, other_name
) subqueryalias
Example at SQL Fiddle
Related Topics
Recursive Query Challenge - Simple Parent/Child Example
Insert-Output Including Column from Other Table
Rails Pg::Undefinedtable: Error: Missing From-Clause Entry for Table
Linked Access Db "Record Has Been Changed by Another User"
Convert Datetime to Unix Timestamp
Efficiently Duplicate Some Rows in Postgresql Table
What Data Can Be Stored in Varbinary Data Type of SQL Server
Why Is Select Count(*) Slower Than Select * in Hive
Sql Server 2005 Unique Constraint on Two Columns
SQL Query of Multi-Member File on As400
Using a SQL Server for Application Logging. Pros/Cons
Combine Multiple Rows into One Space Separated String
Sql-Style Group by Aggregate Functions in Jq (Count, Sum and etc)
How to Copy a Row with Every Column Except Identity Column (Sql Server 2005)