sqlite filtering by sum
Supposing a table created thus:
CREATE TABLE Files (Id INTEGER PRIMARY KEY, FileName TEXT, CreationDate DATE, Size INTEGER);
To get the running sum, use the following query:
SELECT f1.id AS FileId, sum(f2.size) AS RunningSumSize
FROM file f1 INNER JOIN file f2
ON f1.createdDate<=f2.createdDate
GROUP BY FileId
ORDER BY RunningSumSize DESC;
To delete the file ID's above the threshold:
DELETE FROM File WHERE Id IN
(SELECT FileId FROM
(SELECT f1.id AS FileId, sum(f2.size) AS RunningSumSize
FROM file f1 INNER JOIN file f2
ON f1.createdDate<=f2.createdDate
GROUP by FileId
ORDER by RunningSumSize DESC)
WHERE RunningSumSize > :ThresholdSize:);
Note: The order by
is optional.
Performing a prefix computation using SQL without defined procedures
try something like this:
select value,
(select sum(t2.value) from table t2 where t2.id <= t1.id ) as accumulated
from table t1
from: SQLite: accumulator (sum) column in a SELECT statement
How to query sum previous row of the same column with with pgSql
Use user-defined aggregate
Live test: http://sqlfiddle.com/#!17/03ee7/1
DDL
CREATE TABLE t
(grop varchar(1), month_year text, something int)
;
INSERT INTO t
(grop, month_year, something)
VALUES
('a', '201901', -2),
('a', '201902', -4),
('a', '201903', -6),
('a', '201904', 60),
('a', '201905', -2),
('a', '201906', 9),
('a', '201907', 11),
('b', '201901', 100),
('b', '201902', -200),
('b', '201903', 300),
('b', '201904', -50),
('b', '201905', 30),
('b', '201906', -88),
('b', '201907', -86)
;
User-defined aggregate
create or replace function negative_accum(_accumulated_b numeric, _current_b numeric)
returns numeric as
$$
select case when _accumulated_b < 0 then
_accumulated_b + _current_b
else
_current_b
end
$$ language 'sql';
create aggregate negative_summer(numeric)
(
sfunc = negative_accum,
stype = numeric,
initcond = 0
);
select
*,
negative_summer(something) over (order by grop, month_year) as result
from t
The first parameter (_accumulated_b) holds the accumulated value of the column. The second parameter (_current_b) holds the value of the current row's column.
Output:
As for your pseudo-code B3 = A3 + MIN(0, B2)
I used this typical code:
select case when _accumulated_b < 0 then
_accumulated_b + _current_b
else
_current_b
end
That can be written idiomatically in Postgres as:
select _current_b + least(_accumulated_b, 0)
Live test: http://sqlfiddle.com/#!17/70fa8/1
create or replace function negative_accum(_accumulated_b numeric, _current_b numeric)
returns numeric as
$$
select _current_b + least(_accumulated_b, 0)
$$ language 'sql';
You can also use other language with accumulator function, e.g., plpgsql. Note that plpgsql (or perhaps the $$ quote) is not supported in http://sqlfiddle.com. So no live test link, this would work on your machine though:
create or replace function negative_accum(_accumulated_b numeric, _current_b numeric)
returns numeric as
$$begin
return _current_b + least(_accumulated_b, 0);
end$$ language 'plpgsql';
UPDATE
I missed the partition by
, here's an example data (changed 11 to -11) where without partition by
and with partition by
would yield different results:
Live test: http://sqlfiddle.com/#!17/87795/4
INSERT INTO t
(grop, month_year, something)
VALUES
('a', '201901', -2),
('a', '201902', -4),
('a', '201903', -6),
('a', '201904', 60),
('a', '201905', -2),
('a', '201906', 9),
('a', '201907', -11), -- changed this from 11 to -11
('b', '201901', 100),
('b', '201902', -200),
('b', '201903', 300),
('b', '201904', -50),
('b', '201905', 30),
('b', '201906', -88),
('b', '201907', -86)
;
Output:
| grop | month_year | something | result_wrong | result |
|------|------------|-----------|--------------|--------|
| a | 201901 | -2 | -2 | -2 |
| a | 201902 | -4 | -6 | -6 |
| a | 201903 | -6 | -12 | -12 |
| a | 201904 | 60 | 48 | 48 |
| a | 201905 | -2 | -2 | -2 |
| a | 201906 | 9 | 7 | 7 |
| a | 201907 | -11 | -11 | -11 |
| b | 201901 | 100 | 89 | 100 |
| b | 201902 | -200 | -200 | -200 |
| b | 201903 | 300 | 100 | 100 |
| b | 201904 | -50 | -50 | -50 |
| b | 201905 | 30 | -20 | -20 |
| b | 201906 | -88 | -108 | -108 |
| b | 201907 | -86 | -194 | -194 |
Aggregate function in an SQL update query?
UPDATE t1
SET t1.field1 = t2.field2Sum
FROM table1 t1
INNER JOIN (select field3, sum(field2) as field2Sum
from table2
group by field3) as t2
on t2.field3 = t1.field3
Related Topics
SQL Split String by Space into Table in Postgresql
Oracle SQL: Understanding the Behavior of Sys_Guid() When Present in an Inline View
How to Use Group by Based on a Case Statement in Oracle
How to Monitor the Executed SQL Statements on a SQL Server 2005
Parsing Nested Xml into SQL Table
How to Remove SQL Azure Data Sync Objects Manually
Sql Server 2008 - How to Convert Gmt(Utc) Datetime to Local Datetime
How to Use SQL Server Stored Procedures in Microsoft Powerbi
Are There Reasons for Not Storing Boolean Values in SQL as Bit Data Types
Sql Server Left Join with 'Or' Operator
Case Statement in Where Clause - SQL Server
Duration of Data in a Global Temporary Table
Sql: Subquery Has Too Many Columns
Rails - Find with Condition in Rails 4
Are There Any Limits on Length of String in MySQL
How to Get Second Highest Salary Department Wise Without Using Analytical Functions