Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Window running function except current row

I have a theoretical question, so I'm not interested in alternative solutions. Sorry.

Q: Is it possible to get the window running function values for all previous rows, except current?

For example:

with
  t(i,x,y) as (
    values
      (1,1,1),(2,1,3),(3,1,2),
      (4,2,4),(5,2,2),(6,2,8)
    )
select
  t.*,
  sum(y) over (partition by x order by i) - y as sum,
  max(y) over (partition by x order by i) as max,
  count(*) filter (where y > 2) over (partition by x order by i) as cnt
from
  t;

Actual result is

 i | x | y | sum | max | cnt 
---+---+---+-----+-----+-----
 1 | 1 | 1 |   0 |   1 |   0
 2 | 1 | 3 |   1 |   3 |   1
 3 | 1 | 2 |   4 |   3 |   1
 4 | 2 | 4 |   0 |   4 |   1
 5 | 2 | 2 |   4 |   4 |   1
 6 | 2 | 8 |   6 |   8 |   2
(6 rows)

I want to have max and cnt columns behavior like sum column, so, result should be:

 i | x | y | sum | max | cnt 
---+---+---+-----+-----+-----
 1 | 1 | 1 |   0 |     |   0
 2 | 1 | 3 |   1 |   1 |   0
 3 | 1 | 2 |   4 |   3 |   1
 4 | 2 | 4 |   0 |     |   0
 5 | 2 | 2 |   4 |   4 |   1
 6 | 2 | 8 |   6 |   4 |   1
(6 rows)

It can be achieved using simple subquery like

select t.*, lag(y,1) over (partition by x order by i) as yy from t

but is it possible using only window function syntax, without subqueries?

like image 508
Abelisto Avatar asked Mar 09 '16 22:03

Abelisto


People also ask

Does unbounded preceding include current row?

UNBOUNDED PRECEDING indicates that the window starts at the first row of the partition; offset PRECEDING indicates that the window starts a number of rows equivalent to the value of offset before the current row. UNBOUNDED PRECEDING is the default. CURRENT ROW indicates the window begins or ends at the current row.

Can you put a where clause in a window function?

You cannot use window functions in WHERE , GROUP BY , or HAVING .

What is range between unbounded preceding and current row?

The frame, ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, means that the window consists of the first row of the partition and all the rows up to the current row. Each calculation is done over a different set of rows. For example, when performing the calculation for row 4, the rows 1 to 4 are used.

What is frame clause in window function?

Specifies a window frame, which comprises a set of rows relative to the row that is currently being evaluated by the analytic function. After the function processes that row and its window, Vertica advances the current row and adjusts the window boundaries accordingly.


1 Answers

Yes, you can. This does the trick:

with
  t(i,x,y) as (
    values
      (1,1,1),(2,1,3),(3,1,2),
      (4,2,4),(5,2,2),(6,2,8)
    )
select
  t.*,
  sum(y) over w as sum,
  max(y) over w as max,
  count(*) filter (where y > 2) over w as cnt
from t
window w as (partition by x order by i
             rows between unbounded preceding and 1 preceding);

The frame_clause selects just those rows from the window frame that you are interested in.

Note that in the sum column you'll get null rather than 0 because of the frame clause: the first row in the frame has no row before it. You can coalesce() this away if needed.

SQLFiddle

like image 124
Patrick Avatar answered Oct 01 '22 07:10

Patrick