3824 lines
118 KiB
Plaintext
3824 lines
118 KiB
Plaintext
--
|
|
-- WINDOW FUNCTIONS
|
|
--
|
|
CREATE TEMPORARY TABLE empsalary (
|
|
depname varchar,
|
|
empno bigint,
|
|
salary int,
|
|
enroll_date date
|
|
);
|
|
INSERT INTO empsalary VALUES
|
|
('develop', 10, 5200, '2007-08-01'),
|
|
('sales', 1, 5000, '2006-10-01'),
|
|
('personnel', 5, 3500, '2007-12-10'),
|
|
('sales', 4, 4800, '2007-08-08'),
|
|
('personnel', 2, 3900, '2006-12-23'),
|
|
('develop', 7, 4200, '2008-01-01'),
|
|
('develop', 9, 4500, '2008-01-01'),
|
|
('sales', 3, 4800, '2007-08-01'),
|
|
('develop', 8, 6000, '2006-10-01'),
|
|
('develop', 11, 5200, '2007-08-15');
|
|
SELECT depname, empno, salary, sum(salary) OVER (PARTITION BY depname) FROM empsalary ORDER BY depname, salary;
|
|
depname | empno | salary | sum
|
|
-----------+-------+--------+-------
|
|
develop | 7 | 4200 | 25100
|
|
develop | 9 | 4500 | 25100
|
|
develop | 11 | 5200 | 25100
|
|
develop | 10 | 5200 | 25100
|
|
develop | 8 | 6000 | 25100
|
|
personnel | 5 | 3500 | 7400
|
|
personnel | 2 | 3900 | 7400
|
|
sales | 3 | 4800 | 14600
|
|
sales | 4 | 4800 | 14600
|
|
sales | 1 | 5000 | 14600
|
|
(10 rows)
|
|
|
|
SELECT depname, empno, salary, rank() OVER (PARTITION BY depname ORDER BY salary) FROM empsalary;
|
|
depname | empno | salary | rank
|
|
-----------+-------+--------+------
|
|
develop | 7 | 4200 | 1
|
|
develop | 9 | 4500 | 2
|
|
develop | 11 | 5200 | 3
|
|
develop | 10 | 5200 | 3
|
|
develop | 8 | 6000 | 5
|
|
personnel | 5 | 3500 | 1
|
|
personnel | 2 | 3900 | 2
|
|
sales | 3 | 4800 | 1
|
|
sales | 4 | 4800 | 1
|
|
sales | 1 | 5000 | 3
|
|
(10 rows)
|
|
|
|
-- with GROUP BY
|
|
SELECT four, ten, SUM(SUM(four)) OVER (PARTITION BY four), AVG(ten) FROM tenk1
|
|
GROUP BY four, ten ORDER BY four, ten;
|
|
four | ten | sum | avg
|
|
------+-----+------+------------------------
|
|
0 | 0 | 0 | 0.00000000000000000000
|
|
0 | 2 | 0 | 2.0000000000000000
|
|
0 | 4 | 0 | 4.0000000000000000
|
|
0 | 6 | 0 | 6.0000000000000000
|
|
0 | 8 | 0 | 8.0000000000000000
|
|
1 | 1 | 2500 | 1.00000000000000000000
|
|
1 | 3 | 2500 | 3.0000000000000000
|
|
1 | 5 | 2500 | 5.0000000000000000
|
|
1 | 7 | 2500 | 7.0000000000000000
|
|
1 | 9 | 2500 | 9.0000000000000000
|
|
2 | 0 | 5000 | 0.00000000000000000000
|
|
2 | 2 | 5000 | 2.0000000000000000
|
|
2 | 4 | 5000 | 4.0000000000000000
|
|
2 | 6 | 5000 | 6.0000000000000000
|
|
2 | 8 | 5000 | 8.0000000000000000
|
|
3 | 1 | 7500 | 1.00000000000000000000
|
|
3 | 3 | 7500 | 3.0000000000000000
|
|
3 | 5 | 7500 | 5.0000000000000000
|
|
3 | 7 | 7500 | 7.0000000000000000
|
|
3 | 9 | 7500 | 9.0000000000000000
|
|
(20 rows)
|
|
|
|
SELECT depname, empno, salary, sum(salary) OVER w FROM empsalary WINDOW w AS (PARTITION BY depname);
|
|
depname | empno | salary | sum
|
|
-----------+-------+--------+-------
|
|
develop | 11 | 5200 | 25100
|
|
develop | 7 | 4200 | 25100
|
|
develop | 9 | 4500 | 25100
|
|
develop | 8 | 6000 | 25100
|
|
develop | 10 | 5200 | 25100
|
|
personnel | 5 | 3500 | 7400
|
|
personnel | 2 | 3900 | 7400
|
|
sales | 3 | 4800 | 14600
|
|
sales | 1 | 5000 | 14600
|
|
sales | 4 | 4800 | 14600
|
|
(10 rows)
|
|
|
|
SELECT depname, empno, salary, rank() OVER w FROM empsalary WINDOW w AS (PARTITION BY depname ORDER BY salary) ORDER BY rank() OVER w;
|
|
depname | empno | salary | rank
|
|
-----------+-------+--------+------
|
|
develop | 7 | 4200 | 1
|
|
personnel | 5 | 3500 | 1
|
|
sales | 3 | 4800 | 1
|
|
sales | 4 | 4800 | 1
|
|
personnel | 2 | 3900 | 2
|
|
develop | 9 | 4500 | 2
|
|
sales | 1 | 5000 | 3
|
|
develop | 11 | 5200 | 3
|
|
develop | 10 | 5200 | 3
|
|
develop | 8 | 6000 | 5
|
|
(10 rows)
|
|
|
|
-- empty window specification
|
|
SELECT COUNT(*) OVER () FROM tenk1 WHERE unique2 < 10;
|
|
count
|
|
-------
|
|
10
|
|
10
|
|
10
|
|
10
|
|
10
|
|
10
|
|
10
|
|
10
|
|
10
|
|
10
|
|
(10 rows)
|
|
|
|
SELECT COUNT(*) OVER w FROM tenk1 WHERE unique2 < 10 WINDOW w AS ();
|
|
count
|
|
-------
|
|
10
|
|
10
|
|
10
|
|
10
|
|
10
|
|
10
|
|
10
|
|
10
|
|
10
|
|
10
|
|
(10 rows)
|
|
|
|
-- no window operation
|
|
SELECT four FROM tenk1 WHERE FALSE WINDOW w AS (PARTITION BY ten);
|
|
four
|
|
------
|
|
(0 rows)
|
|
|
|
-- cumulative aggregate
|
|
SELECT sum(four) OVER (PARTITION BY ten ORDER BY unique2) AS sum_1, ten, four FROM tenk1 WHERE unique2 < 10;
|
|
sum_1 | ten | four
|
|
-------+-----+------
|
|
0 | 0 | 0
|
|
0 | 0 | 0
|
|
2 | 0 | 2
|
|
3 | 1 | 3
|
|
4 | 1 | 1
|
|
5 | 1 | 1
|
|
3 | 3 | 3
|
|
0 | 4 | 0
|
|
1 | 7 | 1
|
|
1 | 9 | 1
|
|
(10 rows)
|
|
|
|
SELECT row_number() OVER (ORDER BY unique2) FROM tenk1 WHERE unique2 < 10;
|
|
row_number
|
|
------------
|
|
1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
6
|
|
7
|
|
8
|
|
9
|
|
10
|
|
(10 rows)
|
|
|
|
SELECT rank() OVER (PARTITION BY four ORDER BY ten) AS rank_1, ten, four FROM tenk1 WHERE unique2 < 10;
|
|
rank_1 | ten | four
|
|
--------+-----+------
|
|
1 | 0 | 0
|
|
1 | 0 | 0
|
|
3 | 4 | 0
|
|
1 | 1 | 1
|
|
1 | 1 | 1
|
|
3 | 7 | 1
|
|
4 | 9 | 1
|
|
1 | 0 | 2
|
|
1 | 1 | 3
|
|
2 | 3 | 3
|
|
(10 rows)
|
|
|
|
SELECT dense_rank() OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10;
|
|
dense_rank | ten | four
|
|
------------+-----+------
|
|
1 | 0 | 0
|
|
1 | 0 | 0
|
|
2 | 4 | 0
|
|
1 | 1 | 1
|
|
1 | 1 | 1
|
|
2 | 7 | 1
|
|
3 | 9 | 1
|
|
1 | 0 | 2
|
|
1 | 1 | 3
|
|
2 | 3 | 3
|
|
(10 rows)
|
|
|
|
SELECT percent_rank() OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10;
|
|
percent_rank | ten | four
|
|
--------------------+-----+------
|
|
0 | 0 | 0
|
|
0 | 0 | 0
|
|
1 | 4 | 0
|
|
0 | 1 | 1
|
|
0 | 1 | 1
|
|
0.6666666666666666 | 7 | 1
|
|
1 | 9 | 1
|
|
0 | 0 | 2
|
|
0 | 1 | 3
|
|
1 | 3 | 3
|
|
(10 rows)
|
|
|
|
SELECT cume_dist() OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10;
|
|
cume_dist | ten | four
|
|
--------------------+-----+------
|
|
0.6666666666666666 | 0 | 0
|
|
0.6666666666666666 | 0 | 0
|
|
1 | 4 | 0
|
|
0.5 | 1 | 1
|
|
0.5 | 1 | 1
|
|
0.75 | 7 | 1
|
|
1 | 9 | 1
|
|
1 | 0 | 2
|
|
0.5 | 1 | 3
|
|
1 | 3 | 3
|
|
(10 rows)
|
|
|
|
SELECT ntile(3) OVER (ORDER BY ten, four), ten, four FROM tenk1 WHERE unique2 < 10;
|
|
ntile | ten | four
|
|
-------+-----+------
|
|
1 | 0 | 0
|
|
1 | 0 | 0
|
|
1 | 0 | 2
|
|
1 | 1 | 1
|
|
2 | 1 | 1
|
|
2 | 1 | 3
|
|
2 | 3 | 3
|
|
3 | 4 | 0
|
|
3 | 7 | 1
|
|
3 | 9 | 1
|
|
(10 rows)
|
|
|
|
SELECT ntile(NULL) OVER (ORDER BY ten, four), ten, four FROM tenk1 LIMIT 2;
|
|
ntile | ten | four
|
|
-------+-----+------
|
|
| 0 | 0
|
|
| 0 | 0
|
|
(2 rows)
|
|
|
|
SELECT lag(ten) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10;
|
|
lag | ten | four
|
|
-----+-----+------
|
|
| 0 | 0
|
|
0 | 0 | 0
|
|
0 | 4 | 0
|
|
| 1 | 1
|
|
1 | 1 | 1
|
|
1 | 7 | 1
|
|
7 | 9 | 1
|
|
| 0 | 2
|
|
| 1 | 3
|
|
1 | 3 | 3
|
|
(10 rows)
|
|
|
|
SELECT lag(ten, four) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10;
|
|
lag | ten | four
|
|
-----+-----+------
|
|
0 | 0 | 0
|
|
0 | 0 | 0
|
|
4 | 4 | 0
|
|
| 1 | 1
|
|
1 | 1 | 1
|
|
1 | 7 | 1
|
|
7 | 9 | 1
|
|
| 0 | 2
|
|
| 1 | 3
|
|
| 3 | 3
|
|
(10 rows)
|
|
|
|
SELECT lag(ten, four, 0) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10;
|
|
lag | ten | four
|
|
-----+-----+------
|
|
0 | 0 | 0
|
|
0 | 0 | 0
|
|
4 | 4 | 0
|
|
0 | 1 | 1
|
|
1 | 1 | 1
|
|
1 | 7 | 1
|
|
7 | 9 | 1
|
|
0 | 0 | 2
|
|
0 | 1 | 3
|
|
0 | 3 | 3
|
|
(10 rows)
|
|
|
|
SELECT lead(ten) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10;
|
|
lead | ten | four
|
|
------+-----+------
|
|
0 | 0 | 0
|
|
4 | 0 | 0
|
|
| 4 | 0
|
|
1 | 1 | 1
|
|
7 | 1 | 1
|
|
9 | 7 | 1
|
|
| 9 | 1
|
|
| 0 | 2
|
|
3 | 1 | 3
|
|
| 3 | 3
|
|
(10 rows)
|
|
|
|
SELECT lead(ten * 2, 1) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10;
|
|
lead | ten | four
|
|
------+-----+------
|
|
0 | 0 | 0
|
|
8 | 0 | 0
|
|
| 4 | 0
|
|
2 | 1 | 1
|
|
14 | 1 | 1
|
|
18 | 7 | 1
|
|
| 9 | 1
|
|
| 0 | 2
|
|
6 | 1 | 3
|
|
| 3 | 3
|
|
(10 rows)
|
|
|
|
SELECT lead(ten * 2, 1, -1) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10;
|
|
lead | ten | four
|
|
------+-----+------
|
|
0 | 0 | 0
|
|
8 | 0 | 0
|
|
-1 | 4 | 0
|
|
2 | 1 | 1
|
|
14 | 1 | 1
|
|
18 | 7 | 1
|
|
-1 | 9 | 1
|
|
-1 | 0 | 2
|
|
6 | 1 | 3
|
|
-1 | 3 | 3
|
|
(10 rows)
|
|
|
|
SELECT first_value(ten) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10;
|
|
first_value | ten | four
|
|
-------------+-----+------
|
|
0 | 0 | 0
|
|
0 | 0 | 0
|
|
0 | 4 | 0
|
|
1 | 1 | 1
|
|
1 | 1 | 1
|
|
1 | 7 | 1
|
|
1 | 9 | 1
|
|
0 | 0 | 2
|
|
1 | 1 | 3
|
|
1 | 3 | 3
|
|
(10 rows)
|
|
|
|
-- last_value returns the last row of the frame, which is CURRENT ROW in ORDER BY window.
|
|
SELECT last_value(four) OVER (ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10;
|
|
last_value | ten | four
|
|
------------+-----+------
|
|
0 | 0 | 0
|
|
0 | 0 | 2
|
|
0 | 0 | 0
|
|
1 | 1 | 1
|
|
1 | 1 | 3
|
|
1 | 1 | 1
|
|
3 | 3 | 3
|
|
0 | 4 | 0
|
|
1 | 7 | 1
|
|
1 | 9 | 1
|
|
(10 rows)
|
|
|
|
SELECT last_value(ten) OVER (PARTITION BY four), ten, four FROM
|
|
(SELECT * FROM tenk1 WHERE unique2 < 10 ORDER BY four, ten)s
|
|
ORDER BY four, ten;
|
|
last_value | ten | four
|
|
------------+-----+------
|
|
4 | 0 | 0
|
|
4 | 0 | 0
|
|
4 | 4 | 0
|
|
9 | 1 | 1
|
|
9 | 1 | 1
|
|
9 | 7 | 1
|
|
9 | 9 | 1
|
|
0 | 0 | 2
|
|
3 | 1 | 3
|
|
3 | 3 | 3
|
|
(10 rows)
|
|
|
|
SELECT nth_value(ten, four + 1) OVER (PARTITION BY four), ten, four
|
|
FROM (SELECT * FROM tenk1 WHERE unique2 < 10 ORDER BY four, ten)s;
|
|
nth_value | ten | four
|
|
-----------+-----+------
|
|
0 | 0 | 0
|
|
0 | 0 | 0
|
|
0 | 4 | 0
|
|
1 | 1 | 1
|
|
1 | 1 | 1
|
|
1 | 7 | 1
|
|
1 | 9 | 1
|
|
| 0 | 2
|
|
| 1 | 3
|
|
| 3 | 3
|
|
(10 rows)
|
|
|
|
SELECT ten, two, sum(hundred) AS gsum, sum(sum(hundred)) OVER (PARTITION BY two ORDER BY ten) AS wsum
|
|
FROM tenk1 GROUP BY ten, two;
|
|
ten | two | gsum | wsum
|
|
-----+-----+-------+--------
|
|
0 | 0 | 45000 | 45000
|
|
2 | 0 | 47000 | 92000
|
|
4 | 0 | 49000 | 141000
|
|
6 | 0 | 51000 | 192000
|
|
8 | 0 | 53000 | 245000
|
|
1 | 1 | 46000 | 46000
|
|
3 | 1 | 48000 | 94000
|
|
5 | 1 | 50000 | 144000
|
|
7 | 1 | 52000 | 196000
|
|
9 | 1 | 54000 | 250000
|
|
(10 rows)
|
|
|
|
SELECT count(*) OVER (PARTITION BY four), four FROM (SELECT * FROM tenk1 WHERE two = 1)s WHERE unique2 < 10;
|
|
count | four
|
|
-------+------
|
|
4 | 1
|
|
4 | 1
|
|
4 | 1
|
|
4 | 1
|
|
2 | 3
|
|
2 | 3
|
|
(6 rows)
|
|
|
|
SELECT (count(*) OVER (PARTITION BY four ORDER BY ten) +
|
|
sum(hundred) OVER (PARTITION BY four ORDER BY ten))::varchar AS cntsum
|
|
FROM tenk1 WHERE unique2 < 10;
|
|
cntsum
|
|
--------
|
|
22
|
|
22
|
|
87
|
|
24
|
|
24
|
|
82
|
|
92
|
|
51
|
|
92
|
|
136
|
|
(10 rows)
|
|
|
|
-- opexpr with different windows evaluation.
|
|
SELECT * FROM(
|
|
SELECT count(*) OVER (PARTITION BY four ORDER BY ten) +
|
|
sum(hundred) OVER (PARTITION BY two ORDER BY ten) AS total,
|
|
count(*) OVER (PARTITION BY four ORDER BY ten) AS fourcount,
|
|
sum(hundred) OVER (PARTITION BY two ORDER BY ten) AS twosum
|
|
FROM tenk1
|
|
)sub
|
|
WHERE total <> fourcount + twosum;
|
|
total | fourcount | twosum
|
|
-------+-----------+--------
|
|
(0 rows)
|
|
|
|
SELECT avg(four) OVER (PARTITION BY four ORDER BY thousand / 100) FROM tenk1 WHERE unique2 < 10;
|
|
avg
|
|
------------------------
|
|
0.00000000000000000000
|
|
0.00000000000000000000
|
|
0.00000000000000000000
|
|
1.00000000000000000000
|
|
1.00000000000000000000
|
|
1.00000000000000000000
|
|
1.00000000000000000000
|
|
2.0000000000000000
|
|
3.0000000000000000
|
|
3.0000000000000000
|
|
(10 rows)
|
|
|
|
SELECT ten, two, sum(hundred) AS gsum, sum(sum(hundred)) OVER win AS wsum
|
|
FROM tenk1 GROUP BY ten, two WINDOW win AS (PARTITION BY two ORDER BY ten);
|
|
ten | two | gsum | wsum
|
|
-----+-----+-------+--------
|
|
0 | 0 | 45000 | 45000
|
|
2 | 0 | 47000 | 92000
|
|
4 | 0 | 49000 | 141000
|
|
6 | 0 | 51000 | 192000
|
|
8 | 0 | 53000 | 245000
|
|
1 | 1 | 46000 | 46000
|
|
3 | 1 | 48000 | 94000
|
|
5 | 1 | 50000 | 144000
|
|
7 | 1 | 52000 | 196000
|
|
9 | 1 | 54000 | 250000
|
|
(10 rows)
|
|
|
|
-- more than one window with GROUP BY
|
|
SELECT sum(salary),
|
|
row_number() OVER (ORDER BY depname),
|
|
sum(sum(salary)) OVER (ORDER BY depname DESC)
|
|
FROM empsalary GROUP BY depname;
|
|
sum | row_number | sum
|
|
-------+------------+-------
|
|
25100 | 1 | 47100
|
|
7400 | 2 | 22000
|
|
14600 | 3 | 14600
|
|
(3 rows)
|
|
|
|
-- identical windows with different names
|
|
SELECT sum(salary) OVER w1, count(*) OVER w2
|
|
FROM empsalary WINDOW w1 AS (ORDER BY salary), w2 AS (ORDER BY salary);
|
|
sum | count
|
|
-------+-------
|
|
3500 | 1
|
|
7400 | 2
|
|
11600 | 3
|
|
16100 | 4
|
|
25700 | 6
|
|
25700 | 6
|
|
30700 | 7
|
|
41100 | 9
|
|
41100 | 9
|
|
47100 | 10
|
|
(10 rows)
|
|
|
|
-- subplan
|
|
SELECT lead(ten, (SELECT two FROM tenk1 WHERE s.unique2 = unique2)) OVER (PARTITION BY four ORDER BY ten)
|
|
FROM tenk1 s WHERE unique2 < 10;
|
|
lead
|
|
------
|
|
0
|
|
0
|
|
4
|
|
1
|
|
7
|
|
9
|
|
|
|
0
|
|
3
|
|
|
|
(10 rows)
|
|
|
|
-- empty table
|
|
SELECT count(*) OVER (PARTITION BY four) FROM (SELECT * FROM tenk1 WHERE FALSE)s;
|
|
count
|
|
-------
|
|
(0 rows)
|
|
|
|
-- mixture of agg/wfunc in the same window
|
|
SELECT sum(salary) OVER w, rank() OVER w FROM empsalary WINDOW w AS (PARTITION BY depname ORDER BY salary DESC);
|
|
sum | rank
|
|
-------+------
|
|
6000 | 1
|
|
16400 | 2
|
|
16400 | 2
|
|
20900 | 4
|
|
25100 | 5
|
|
3900 | 1
|
|
7400 | 2
|
|
5000 | 1
|
|
14600 | 2
|
|
14600 | 2
|
|
(10 rows)
|
|
|
|
-- strict aggs
|
|
SELECT empno, depname, salary, bonus, depadj, MIN(bonus) OVER (ORDER BY empno), MAX(depadj) OVER () FROM(
|
|
SELECT *,
|
|
CASE WHEN enroll_date < '2008-01-01' THEN 2008 - extract(YEAR FROM enroll_date) END * 500 AS bonus,
|
|
CASE WHEN
|
|
AVG(salary) OVER (PARTITION BY depname) < salary
|
|
THEN 200 END AS depadj FROM empsalary
|
|
)s;
|
|
empno | depname | salary | bonus | depadj | min | max
|
|
-------+-----------+--------+-------+--------+------+-----
|
|
1 | sales | 5000 | 1000 | 200 | 1000 | 200
|
|
2 | personnel | 3900 | 1000 | 200 | 1000 | 200
|
|
3 | sales | 4800 | 500 | | 500 | 200
|
|
4 | sales | 4800 | 500 | | 500 | 200
|
|
5 | personnel | 3500 | 500 | | 500 | 200
|
|
7 | develop | 4200 | | | 500 | 200
|
|
8 | develop | 6000 | 1000 | 200 | 500 | 200
|
|
9 | develop | 4500 | | | 500 | 200
|
|
10 | develop | 5200 | 500 | 200 | 500 | 200
|
|
11 | develop | 5200 | 500 | 200 | 500 | 200
|
|
(10 rows)
|
|
|
|
-- window function over ungrouped agg over empty row set (bug before 9.1)
|
|
SELECT SUM(COUNT(f1)) OVER () FROM int4_tbl WHERE f1=42;
|
|
sum
|
|
-----
|
|
0
|
|
(1 row)
|
|
|
|
-- window function with ORDER BY an expression involving aggregates (9.1 bug)
|
|
select ten,
|
|
sum(unique1) + sum(unique2) as res,
|
|
rank() over (order by sum(unique1) + sum(unique2)) as rank
|
|
from tenk1
|
|
group by ten order by ten;
|
|
ten | res | rank
|
|
-----+----------+------
|
|
0 | 9976146 | 4
|
|
1 | 10114187 | 9
|
|
2 | 10059554 | 8
|
|
3 | 9878541 | 1
|
|
4 | 9881005 | 2
|
|
5 | 9981670 | 5
|
|
6 | 9947099 | 3
|
|
7 | 10120309 | 10
|
|
8 | 9991305 | 6
|
|
9 | 10040184 | 7
|
|
(10 rows)
|
|
|
|
-- window and aggregate with GROUP BY expression (9.2 bug)
|
|
explain (costs off)
|
|
select first_value(max(x)) over (), y
|
|
from (select unique1 as x, ten+four as y from tenk1) ss
|
|
group by y;
|
|
QUERY PLAN
|
|
---------------------------------------------
|
|
WindowAgg
|
|
-> HashAggregate
|
|
Group Key: (tenk1.ten + tenk1.four)
|
|
-> Seq Scan on tenk1
|
|
(4 rows)
|
|
|
|
-- test non-default frame specifications
|
|
SELECT four, ten,
|
|
sum(ten) over (partition by four order by ten),
|
|
last_value(ten) over (partition by four order by ten)
|
|
FROM (select distinct ten, four from tenk1) ss;
|
|
four | ten | sum | last_value
|
|
------+-----+-----+------------
|
|
0 | 0 | 0 | 0
|
|
0 | 2 | 2 | 2
|
|
0 | 4 | 6 | 4
|
|
0 | 6 | 12 | 6
|
|
0 | 8 | 20 | 8
|
|
1 | 1 | 1 | 1
|
|
1 | 3 | 4 | 3
|
|
1 | 5 | 9 | 5
|
|
1 | 7 | 16 | 7
|
|
1 | 9 | 25 | 9
|
|
2 | 0 | 0 | 0
|
|
2 | 2 | 2 | 2
|
|
2 | 4 | 6 | 4
|
|
2 | 6 | 12 | 6
|
|
2 | 8 | 20 | 8
|
|
3 | 1 | 1 | 1
|
|
3 | 3 | 4 | 3
|
|
3 | 5 | 9 | 5
|
|
3 | 7 | 16 | 7
|
|
3 | 9 | 25 | 9
|
|
(20 rows)
|
|
|
|
SELECT four, ten,
|
|
sum(ten) over (partition by four order by ten range between unbounded preceding and current row),
|
|
last_value(ten) over (partition by four order by ten range between unbounded preceding and current row)
|
|
FROM (select distinct ten, four from tenk1) ss;
|
|
four | ten | sum | last_value
|
|
------+-----+-----+------------
|
|
0 | 0 | 0 | 0
|
|
0 | 2 | 2 | 2
|
|
0 | 4 | 6 | 4
|
|
0 | 6 | 12 | 6
|
|
0 | 8 | 20 | 8
|
|
1 | 1 | 1 | 1
|
|
1 | 3 | 4 | 3
|
|
1 | 5 | 9 | 5
|
|
1 | 7 | 16 | 7
|
|
1 | 9 | 25 | 9
|
|
2 | 0 | 0 | 0
|
|
2 | 2 | 2 | 2
|
|
2 | 4 | 6 | 4
|
|
2 | 6 | 12 | 6
|
|
2 | 8 | 20 | 8
|
|
3 | 1 | 1 | 1
|
|
3 | 3 | 4 | 3
|
|
3 | 5 | 9 | 5
|
|
3 | 7 | 16 | 7
|
|
3 | 9 | 25 | 9
|
|
(20 rows)
|
|
|
|
SELECT four, ten,
|
|
sum(ten) over (partition by four order by ten range between unbounded preceding and unbounded following),
|
|
last_value(ten) over (partition by four order by ten range between unbounded preceding and unbounded following)
|
|
FROM (select distinct ten, four from tenk1) ss;
|
|
four | ten | sum | last_value
|
|
------+-----+-----+------------
|
|
0 | 0 | 20 | 8
|
|
0 | 2 | 20 | 8
|
|
0 | 4 | 20 | 8
|
|
0 | 6 | 20 | 8
|
|
0 | 8 | 20 | 8
|
|
1 | 1 | 25 | 9
|
|
1 | 3 | 25 | 9
|
|
1 | 5 | 25 | 9
|
|
1 | 7 | 25 | 9
|
|
1 | 9 | 25 | 9
|
|
2 | 0 | 20 | 8
|
|
2 | 2 | 20 | 8
|
|
2 | 4 | 20 | 8
|
|
2 | 6 | 20 | 8
|
|
2 | 8 | 20 | 8
|
|
3 | 1 | 25 | 9
|
|
3 | 3 | 25 | 9
|
|
3 | 5 | 25 | 9
|
|
3 | 7 | 25 | 9
|
|
3 | 9 | 25 | 9
|
|
(20 rows)
|
|
|
|
SELECT four, ten/4 as two,
|
|
sum(ten/4) over (partition by four order by ten/4 range between unbounded preceding and current row),
|
|
last_value(ten/4) over (partition by four order by ten/4 range between unbounded preceding and current row)
|
|
FROM (select distinct ten, four from tenk1) ss;
|
|
four | two | sum | last_value
|
|
------+-----+-----+------------
|
|
0 | 0 | 0 | 0
|
|
0 | 0 | 0 | 0
|
|
0 | 1 | 2 | 1
|
|
0 | 1 | 2 | 1
|
|
0 | 2 | 4 | 2
|
|
1 | 0 | 0 | 0
|
|
1 | 0 | 0 | 0
|
|
1 | 1 | 2 | 1
|
|
1 | 1 | 2 | 1
|
|
1 | 2 | 4 | 2
|
|
2 | 0 | 0 | 0
|
|
2 | 0 | 0 | 0
|
|
2 | 1 | 2 | 1
|
|
2 | 1 | 2 | 1
|
|
2 | 2 | 4 | 2
|
|
3 | 0 | 0 | 0
|
|
3 | 0 | 0 | 0
|
|
3 | 1 | 2 | 1
|
|
3 | 1 | 2 | 1
|
|
3 | 2 | 4 | 2
|
|
(20 rows)
|
|
|
|
SELECT four, ten/4 as two,
|
|
sum(ten/4) over (partition by four order by ten/4 rows between unbounded preceding and current row),
|
|
last_value(ten/4) over (partition by four order by ten/4 rows between unbounded preceding and current row)
|
|
FROM (select distinct ten, four from tenk1) ss;
|
|
four | two | sum | last_value
|
|
------+-----+-----+------------
|
|
0 | 0 | 0 | 0
|
|
0 | 0 | 0 | 0
|
|
0 | 1 | 1 | 1
|
|
0 | 1 | 2 | 1
|
|
0 | 2 | 4 | 2
|
|
1 | 0 | 0 | 0
|
|
1 | 0 | 0 | 0
|
|
1 | 1 | 1 | 1
|
|
1 | 1 | 2 | 1
|
|
1 | 2 | 4 | 2
|
|
2 | 0 | 0 | 0
|
|
2 | 0 | 0 | 0
|
|
2 | 1 | 1 | 1
|
|
2 | 1 | 2 | 1
|
|
2 | 2 | 4 | 2
|
|
3 | 0 | 0 | 0
|
|
3 | 0 | 0 | 0
|
|
3 | 1 | 1 | 1
|
|
3 | 1 | 2 | 1
|
|
3 | 2 | 4 | 2
|
|
(20 rows)
|
|
|
|
SELECT sum(unique1) over (order by four range between current row and unbounded following),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
45 | 0 | 0
|
|
45 | 8 | 0
|
|
45 | 4 | 0
|
|
33 | 5 | 1
|
|
33 | 9 | 1
|
|
33 | 1 | 1
|
|
18 | 6 | 2
|
|
18 | 2 | 2
|
|
10 | 3 | 3
|
|
10 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (rows between current row and unbounded following),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
45 | 4 | 0
|
|
41 | 2 | 2
|
|
39 | 1 | 1
|
|
38 | 6 | 2
|
|
32 | 9 | 1
|
|
23 | 8 | 0
|
|
15 | 5 | 1
|
|
10 | 3 | 3
|
|
7 | 7 | 3
|
|
0 | 0 | 0
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (rows between 2 preceding and 2 following),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
7 | 4 | 0
|
|
13 | 2 | 2
|
|
22 | 1 | 1
|
|
26 | 6 | 2
|
|
29 | 9 | 1
|
|
31 | 8 | 0
|
|
32 | 5 | 1
|
|
23 | 3 | 3
|
|
15 | 7 | 3
|
|
10 | 0 | 0
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (rows between 2 preceding and 2 following exclude no others),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
7 | 4 | 0
|
|
13 | 2 | 2
|
|
22 | 1 | 1
|
|
26 | 6 | 2
|
|
29 | 9 | 1
|
|
31 | 8 | 0
|
|
32 | 5 | 1
|
|
23 | 3 | 3
|
|
15 | 7 | 3
|
|
10 | 0 | 0
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (rows between 2 preceding and 2 following exclude current row),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
3 | 4 | 0
|
|
11 | 2 | 2
|
|
21 | 1 | 1
|
|
20 | 6 | 2
|
|
20 | 9 | 1
|
|
23 | 8 | 0
|
|
27 | 5 | 1
|
|
20 | 3 | 3
|
|
8 | 7 | 3
|
|
10 | 0 | 0
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (rows between 2 preceding and 2 following exclude group),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
| 4 | 0
|
|
| 2 | 2
|
|
| 1 | 1
|
|
| 6 | 2
|
|
| 9 | 1
|
|
| 8 | 0
|
|
| 5 | 1
|
|
| 3 | 3
|
|
| 7 | 3
|
|
| 0 | 0
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (rows between 2 preceding and 2 following exclude ties),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
4 | 4 | 0
|
|
2 | 2 | 2
|
|
1 | 1 | 1
|
|
6 | 6 | 2
|
|
9 | 9 | 1
|
|
8 | 8 | 0
|
|
5 | 5 | 1
|
|
3 | 3 | 3
|
|
7 | 7 | 3
|
|
0 | 0 | 0
|
|
(10 rows)
|
|
|
|
SELECT first_value(unique1) over (ORDER BY four rows between current row and 2 following exclude current row),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
first_value | unique1 | four
|
|
-------------+---------+------
|
|
8 | 0 | 0
|
|
4 | 8 | 0
|
|
5 | 4 | 0
|
|
9 | 5 | 1
|
|
1 | 9 | 1
|
|
6 | 1 | 1
|
|
2 | 6 | 2
|
|
3 | 2 | 2
|
|
7 | 3 | 3
|
|
| 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT first_value(unique1) over (ORDER BY four rows between current row and 2 following exclude group),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
first_value | unique1 | four
|
|
-------------+---------+------
|
|
| 0 | 0
|
|
5 | 8 | 0
|
|
5 | 4 | 0
|
|
| 5 | 1
|
|
6 | 9 | 1
|
|
6 | 1 | 1
|
|
3 | 6 | 2
|
|
3 | 2 | 2
|
|
| 3 | 3
|
|
| 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT first_value(unique1) over (ORDER BY four rows between current row and 2 following exclude ties),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
first_value | unique1 | four
|
|
-------------+---------+------
|
|
0 | 0 | 0
|
|
8 | 8 | 0
|
|
4 | 4 | 0
|
|
5 | 5 | 1
|
|
9 | 9 | 1
|
|
1 | 1 | 1
|
|
6 | 6 | 2
|
|
2 | 2 | 2
|
|
3 | 3 | 3
|
|
7 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT last_value(unique1) over (ORDER BY four rows between current row and 2 following exclude current row),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
last_value | unique1 | four
|
|
------------+---------+------
|
|
4 | 0 | 0
|
|
5 | 8 | 0
|
|
9 | 4 | 0
|
|
1 | 5 | 1
|
|
6 | 9 | 1
|
|
2 | 1 | 1
|
|
3 | 6 | 2
|
|
7 | 2 | 2
|
|
7 | 3 | 3
|
|
| 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT last_value(unique1) over (ORDER BY four rows between current row and 2 following exclude group),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
last_value | unique1 | four
|
|
------------+---------+------
|
|
| 0 | 0
|
|
5 | 8 | 0
|
|
9 | 4 | 0
|
|
| 5 | 1
|
|
6 | 9 | 1
|
|
2 | 1 | 1
|
|
3 | 6 | 2
|
|
7 | 2 | 2
|
|
| 3 | 3
|
|
| 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT last_value(unique1) over (ORDER BY four rows between current row and 2 following exclude ties),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
last_value | unique1 | four
|
|
------------+---------+------
|
|
0 | 0 | 0
|
|
5 | 8 | 0
|
|
9 | 4 | 0
|
|
5 | 5 | 1
|
|
6 | 9 | 1
|
|
2 | 1 | 1
|
|
3 | 6 | 2
|
|
7 | 2 | 2
|
|
3 | 3 | 3
|
|
7 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (rows between 2 preceding and 1 preceding),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
| 4 | 0
|
|
4 | 2 | 2
|
|
6 | 1 | 1
|
|
3 | 6 | 2
|
|
7 | 9 | 1
|
|
15 | 8 | 0
|
|
17 | 5 | 1
|
|
13 | 3 | 3
|
|
8 | 7 | 3
|
|
10 | 0 | 0
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (rows between 1 following and 3 following),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
9 | 4 | 0
|
|
16 | 2 | 2
|
|
23 | 1 | 1
|
|
22 | 6 | 2
|
|
16 | 9 | 1
|
|
15 | 8 | 0
|
|
10 | 5 | 1
|
|
7 | 3 | 3
|
|
0 | 7 | 3
|
|
| 0 | 0
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (rows between unbounded preceding and 1 following),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
6 | 4 | 0
|
|
7 | 2 | 2
|
|
13 | 1 | 1
|
|
22 | 6 | 2
|
|
30 | 9 | 1
|
|
35 | 8 | 0
|
|
38 | 5 | 1
|
|
45 | 3 | 3
|
|
45 | 7 | 3
|
|
45 | 0 | 0
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (w range between current row and unbounded following),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10 WINDOW w AS (order by four);
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
45 | 0 | 0
|
|
45 | 8 | 0
|
|
45 | 4 | 0
|
|
33 | 5 | 1
|
|
33 | 9 | 1
|
|
33 | 1 | 1
|
|
18 | 6 | 2
|
|
18 | 2 | 2
|
|
10 | 3 | 3
|
|
10 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (w range between unbounded preceding and current row exclude current row),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10 WINDOW w AS (order by four);
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
12 | 0 | 0
|
|
4 | 8 | 0
|
|
8 | 4 | 0
|
|
22 | 5 | 1
|
|
18 | 9 | 1
|
|
26 | 1 | 1
|
|
29 | 6 | 2
|
|
33 | 2 | 2
|
|
42 | 3 | 3
|
|
38 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (w range between unbounded preceding and current row exclude group),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10 WINDOW w AS (order by four);
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
| 0 | 0
|
|
| 8 | 0
|
|
| 4 | 0
|
|
12 | 5 | 1
|
|
12 | 9 | 1
|
|
12 | 1 | 1
|
|
27 | 6 | 2
|
|
27 | 2 | 2
|
|
35 | 3 | 3
|
|
35 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (w range between unbounded preceding and current row exclude ties),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10 WINDOW w AS (order by four);
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
0 | 0 | 0
|
|
8 | 8 | 0
|
|
4 | 4 | 0
|
|
17 | 5 | 1
|
|
21 | 9 | 1
|
|
13 | 1 | 1
|
|
33 | 6 | 2
|
|
29 | 2 | 2
|
|
38 | 3 | 3
|
|
42 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT first_value(unique1) over w,
|
|
nth_value(unique1, 2) over w AS nth_2,
|
|
last_value(unique1) over w, unique1, four
|
|
FROM tenk1 WHERE unique1 < 10
|
|
WINDOW w AS (order by four range between current row and unbounded following);
|
|
first_value | nth_2 | last_value | unique1 | four
|
|
-------------+-------+------------+---------+------
|
|
0 | 8 | 7 | 0 | 0
|
|
0 | 8 | 7 | 8 | 0
|
|
0 | 8 | 7 | 4 | 0
|
|
5 | 9 | 7 | 5 | 1
|
|
5 | 9 | 7 | 9 | 1
|
|
5 | 9 | 7 | 1 | 1
|
|
6 | 2 | 7 | 6 | 2
|
|
6 | 2 | 7 | 2 | 2
|
|
3 | 7 | 7 | 3 | 3
|
|
3 | 7 | 7 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over
|
|
(order by unique1
|
|
rows (SELECT unique1 FROM tenk1 ORDER BY unique1 LIMIT 1) + 1 PRECEDING),
|
|
unique1
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1
|
|
-----+---------
|
|
0 | 0
|
|
1 | 1
|
|
3 | 2
|
|
5 | 3
|
|
7 | 4
|
|
9 | 5
|
|
11 | 6
|
|
13 | 7
|
|
15 | 8
|
|
17 | 9
|
|
(10 rows)
|
|
|
|
CREATE TEMP VIEW v_window AS
|
|
SELECT i, sum(i) over (order by i rows between 1 preceding and 1 following) as sum_rows
|
|
FROM generate_series(1, 10) i;
|
|
SELECT * FROM v_window;
|
|
i | sum_rows
|
|
----+----------
|
|
1 | 3
|
|
2 | 6
|
|
3 | 9
|
|
4 | 12
|
|
5 | 15
|
|
6 | 18
|
|
7 | 21
|
|
8 | 24
|
|
9 | 27
|
|
10 | 19
|
|
(10 rows)
|
|
|
|
SELECT pg_get_viewdef('v_window');
|
|
pg_get_viewdef
|
|
---------------------------------------------------------------------------------------
|
|
SELECT i.i, +
|
|
sum(i.i) OVER (ORDER BY i.i ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS sum_rows+
|
|
FROM generate_series(1, 10) i(i);
|
|
(1 row)
|
|
|
|
CREATE OR REPLACE TEMP VIEW v_window AS
|
|
SELECT i, sum(i) over (order by i rows between 1 preceding and 1 following
|
|
exclude current row) as sum_rows FROM generate_series(1, 10) i;
|
|
SELECT * FROM v_window;
|
|
i | sum_rows
|
|
----+----------
|
|
1 | 2
|
|
2 | 4
|
|
3 | 6
|
|
4 | 8
|
|
5 | 10
|
|
6 | 12
|
|
7 | 14
|
|
8 | 16
|
|
9 | 18
|
|
10 | 9
|
|
(10 rows)
|
|
|
|
SELECT pg_get_viewdef('v_window');
|
|
pg_get_viewdef
|
|
-----------------------------------------------------------------------------------------------------------
|
|
SELECT i.i, +
|
|
sum(i.i) OVER (ORDER BY i.i ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING EXCLUDE CURRENT ROW) AS sum_rows+
|
|
FROM generate_series(1, 10) i(i);
|
|
(1 row)
|
|
|
|
CREATE OR REPLACE TEMP VIEW v_window AS
|
|
SELECT i, sum(i) over (order by i rows between 1 preceding and 1 following
|
|
exclude group) as sum_rows FROM generate_series(1, 10) i;
|
|
SELECT * FROM v_window;
|
|
i | sum_rows
|
|
----+----------
|
|
1 | 2
|
|
2 | 4
|
|
3 | 6
|
|
4 | 8
|
|
5 | 10
|
|
6 | 12
|
|
7 | 14
|
|
8 | 16
|
|
9 | 18
|
|
10 | 9
|
|
(10 rows)
|
|
|
|
SELECT pg_get_viewdef('v_window');
|
|
pg_get_viewdef
|
|
-----------------------------------------------------------------------------------------------------
|
|
SELECT i.i, +
|
|
sum(i.i) OVER (ORDER BY i.i ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING EXCLUDE GROUP) AS sum_rows+
|
|
FROM generate_series(1, 10) i(i);
|
|
(1 row)
|
|
|
|
CREATE OR REPLACE TEMP VIEW v_window AS
|
|
SELECT i, sum(i) over (order by i rows between 1 preceding and 1 following
|
|
exclude ties) as sum_rows FROM generate_series(1, 10) i;
|
|
SELECT * FROM v_window;
|
|
i | sum_rows
|
|
----+----------
|
|
1 | 3
|
|
2 | 6
|
|
3 | 9
|
|
4 | 12
|
|
5 | 15
|
|
6 | 18
|
|
7 | 21
|
|
8 | 24
|
|
9 | 27
|
|
10 | 19
|
|
(10 rows)
|
|
|
|
SELECT pg_get_viewdef('v_window');
|
|
pg_get_viewdef
|
|
----------------------------------------------------------------------------------------------------
|
|
SELECT i.i, +
|
|
sum(i.i) OVER (ORDER BY i.i ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING EXCLUDE TIES) AS sum_rows+
|
|
FROM generate_series(1, 10) i(i);
|
|
(1 row)
|
|
|
|
CREATE OR REPLACE TEMP VIEW v_window AS
|
|
SELECT i, sum(i) over (order by i rows between 1 preceding and 1 following
|
|
exclude no others) as sum_rows FROM generate_series(1, 10) i;
|
|
SELECT * FROM v_window;
|
|
i | sum_rows
|
|
----+----------
|
|
1 | 3
|
|
2 | 6
|
|
3 | 9
|
|
4 | 12
|
|
5 | 15
|
|
6 | 18
|
|
7 | 21
|
|
8 | 24
|
|
9 | 27
|
|
10 | 19
|
|
(10 rows)
|
|
|
|
SELECT pg_get_viewdef('v_window');
|
|
pg_get_viewdef
|
|
---------------------------------------------------------------------------------------
|
|
SELECT i.i, +
|
|
sum(i.i) OVER (ORDER BY i.i ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS sum_rows+
|
|
FROM generate_series(1, 10) i(i);
|
|
(1 row)
|
|
|
|
CREATE OR REPLACE TEMP VIEW v_window AS
|
|
SELECT i, sum(i) over (order by i groups between 1 preceding and 1 following) as sum_rows FROM generate_series(1, 10) i;
|
|
SELECT * FROM v_window;
|
|
i | sum_rows
|
|
----+----------
|
|
1 | 3
|
|
2 | 6
|
|
3 | 9
|
|
4 | 12
|
|
5 | 15
|
|
6 | 18
|
|
7 | 21
|
|
8 | 24
|
|
9 | 27
|
|
10 | 19
|
|
(10 rows)
|
|
|
|
SELECT pg_get_viewdef('v_window');
|
|
pg_get_viewdef
|
|
-----------------------------------------------------------------------------------------
|
|
SELECT i.i, +
|
|
sum(i.i) OVER (ORDER BY i.i GROUPS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS sum_rows+
|
|
FROM generate_series(1, 10) i(i);
|
|
(1 row)
|
|
|
|
DROP VIEW v_window;
|
|
CREATE TEMP VIEW v_window AS
|
|
SELECT i, min(i) over (order by i range between '1 day' preceding and '10 days' following) as min_i
|
|
FROM generate_series(now(), now()+'100 days'::interval, '1 hour') i;
|
|
SELECT pg_get_viewdef('v_window');
|
|
pg_get_viewdef
|
|
---------------------------------------------------------------------------------------------------------------------------
|
|
SELECT i.i, +
|
|
min(i.i) OVER (ORDER BY i.i RANGE BETWEEN '@ 1 day'::interval PRECEDING AND '@ 10 days'::interval FOLLOWING) AS min_i+
|
|
FROM generate_series(now(), (now() + '@ 100 days'::interval), '@ 1 hour'::interval) i(i);
|
|
(1 row)
|
|
|
|
-- RANGE offset PRECEDING/FOLLOWING tests
|
|
SELECT sum(unique1) over (order by four range between 2::int8 preceding and 1::int2 preceding),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
| 0 | 0
|
|
| 8 | 0
|
|
| 4 | 0
|
|
12 | 5 | 1
|
|
12 | 9 | 1
|
|
12 | 1 | 1
|
|
27 | 6 | 2
|
|
27 | 2 | 2
|
|
23 | 3 | 3
|
|
23 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (order by four desc range between 2::int8 preceding and 1::int2 preceding),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
| 3 | 3
|
|
| 7 | 3
|
|
10 | 6 | 2
|
|
10 | 2 | 2
|
|
18 | 9 | 1
|
|
18 | 5 | 1
|
|
18 | 1 | 1
|
|
23 | 0 | 0
|
|
23 | 8 | 0
|
|
23 | 4 | 0
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (order by four range between 2::int8 preceding and 1::int2 preceding exclude no others),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
| 0 | 0
|
|
| 8 | 0
|
|
| 4 | 0
|
|
12 | 5 | 1
|
|
12 | 9 | 1
|
|
12 | 1 | 1
|
|
27 | 6 | 2
|
|
27 | 2 | 2
|
|
23 | 3 | 3
|
|
23 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (order by four range between 2::int8 preceding and 1::int2 preceding exclude current row),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
| 0 | 0
|
|
| 8 | 0
|
|
| 4 | 0
|
|
12 | 5 | 1
|
|
12 | 9 | 1
|
|
12 | 1 | 1
|
|
27 | 6 | 2
|
|
27 | 2 | 2
|
|
23 | 3 | 3
|
|
23 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (order by four range between 2::int8 preceding and 1::int2 preceding exclude group),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
| 0 | 0
|
|
| 8 | 0
|
|
| 4 | 0
|
|
12 | 5 | 1
|
|
12 | 9 | 1
|
|
12 | 1 | 1
|
|
27 | 6 | 2
|
|
27 | 2 | 2
|
|
23 | 3 | 3
|
|
23 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (order by four range between 2::int8 preceding and 1::int2 preceding exclude ties),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
| 0 | 0
|
|
| 8 | 0
|
|
| 4 | 0
|
|
12 | 5 | 1
|
|
12 | 9 | 1
|
|
12 | 1 | 1
|
|
27 | 6 | 2
|
|
27 | 2 | 2
|
|
23 | 3 | 3
|
|
23 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (order by four range between 2::int8 preceding and 6::int2 following exclude ties),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
33 | 0 | 0
|
|
41 | 8 | 0
|
|
37 | 4 | 0
|
|
35 | 5 | 1
|
|
39 | 9 | 1
|
|
31 | 1 | 1
|
|
43 | 6 | 2
|
|
39 | 2 | 2
|
|
26 | 3 | 3
|
|
30 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (order by four range between 2::int8 preceding and 6::int2 following exclude group),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
33 | 0 | 0
|
|
33 | 8 | 0
|
|
33 | 4 | 0
|
|
30 | 5 | 1
|
|
30 | 9 | 1
|
|
30 | 1 | 1
|
|
37 | 6 | 2
|
|
37 | 2 | 2
|
|
23 | 3 | 3
|
|
23 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (partition by four order by unique1 range between 5::int8 preceding and 6::int2 following),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
4 | 0 | 0
|
|
12 | 4 | 0
|
|
12 | 8 | 0
|
|
6 | 1 | 1
|
|
15 | 5 | 1
|
|
14 | 9 | 1
|
|
8 | 2 | 2
|
|
8 | 6 | 2
|
|
10 | 3 | 3
|
|
10 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (partition by four order by unique1 range between 5::int8 preceding and 6::int2 following
|
|
exclude current row),unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
4 | 0 | 0
|
|
8 | 4 | 0
|
|
4 | 8 | 0
|
|
5 | 1 | 1
|
|
10 | 5 | 1
|
|
5 | 9 | 1
|
|
6 | 2 | 2
|
|
2 | 6 | 2
|
|
7 | 3 | 3
|
|
3 | 7 | 3
|
|
(10 rows)
|
|
|
|
select sum(salary) over (order by enroll_date range between '1 year'::interval preceding and '1 year'::interval following),
|
|
salary, enroll_date from empsalary;
|
|
sum | salary | enroll_date
|
|
-------+--------+-------------
|
|
34900 | 5000 | 10-01-2006
|
|
34900 | 6000 | 10-01-2006
|
|
38400 | 3900 | 12-23-2006
|
|
47100 | 4800 | 08-01-2007
|
|
47100 | 5200 | 08-01-2007
|
|
47100 | 4800 | 08-08-2007
|
|
47100 | 5200 | 08-15-2007
|
|
36100 | 3500 | 12-10-2007
|
|
32200 | 4500 | 01-01-2008
|
|
32200 | 4200 | 01-01-2008
|
|
(10 rows)
|
|
|
|
select sum(salary) over (order by enroll_date desc range between '1 year'::interval preceding and '1 year'::interval following),
|
|
salary, enroll_date from empsalary;
|
|
sum | salary | enroll_date
|
|
-------+--------+-------------
|
|
32200 | 4200 | 01-01-2008
|
|
32200 | 4500 | 01-01-2008
|
|
36100 | 3500 | 12-10-2007
|
|
47100 | 5200 | 08-15-2007
|
|
47100 | 4800 | 08-08-2007
|
|
47100 | 4800 | 08-01-2007
|
|
47100 | 5200 | 08-01-2007
|
|
38400 | 3900 | 12-23-2006
|
|
34900 | 5000 | 10-01-2006
|
|
34900 | 6000 | 10-01-2006
|
|
(10 rows)
|
|
|
|
select sum(salary) over (order by enroll_date desc range between '1 year'::interval following and '1 year'::interval following),
|
|
salary, enroll_date from empsalary;
|
|
sum | salary | enroll_date
|
|
-----+--------+-------------
|
|
| 4200 | 01-01-2008
|
|
| 4500 | 01-01-2008
|
|
| 3500 | 12-10-2007
|
|
| 5200 | 08-15-2007
|
|
| 4800 | 08-08-2007
|
|
| 4800 | 08-01-2007
|
|
| 5200 | 08-01-2007
|
|
| 3900 | 12-23-2006
|
|
| 5000 | 10-01-2006
|
|
| 6000 | 10-01-2006
|
|
(10 rows)
|
|
|
|
select sum(salary) over (order by enroll_date range between '1 year'::interval preceding and '1 year'::interval following
|
|
exclude current row), salary, enroll_date from empsalary;
|
|
sum | salary | enroll_date
|
|
-------+--------+-------------
|
|
29900 | 5000 | 10-01-2006
|
|
28900 | 6000 | 10-01-2006
|
|
34500 | 3900 | 12-23-2006
|
|
42300 | 4800 | 08-01-2007
|
|
41900 | 5200 | 08-01-2007
|
|
42300 | 4800 | 08-08-2007
|
|
41900 | 5200 | 08-15-2007
|
|
32600 | 3500 | 12-10-2007
|
|
27700 | 4500 | 01-01-2008
|
|
28000 | 4200 | 01-01-2008
|
|
(10 rows)
|
|
|
|
select sum(salary) over (order by enroll_date range between '1 year'::interval preceding and '1 year'::interval following
|
|
exclude group), salary, enroll_date from empsalary;
|
|
sum | salary | enroll_date
|
|
-------+--------+-------------
|
|
23900 | 5000 | 10-01-2006
|
|
23900 | 6000 | 10-01-2006
|
|
34500 | 3900 | 12-23-2006
|
|
37100 | 4800 | 08-01-2007
|
|
37100 | 5200 | 08-01-2007
|
|
42300 | 4800 | 08-08-2007
|
|
41900 | 5200 | 08-15-2007
|
|
32600 | 3500 | 12-10-2007
|
|
23500 | 4500 | 01-01-2008
|
|
23500 | 4200 | 01-01-2008
|
|
(10 rows)
|
|
|
|
select sum(salary) over (order by enroll_date range between '1 year'::interval preceding and '1 year'::interval following
|
|
exclude ties), salary, enroll_date from empsalary;
|
|
sum | salary | enroll_date
|
|
-------+--------+-------------
|
|
28900 | 5000 | 10-01-2006
|
|
29900 | 6000 | 10-01-2006
|
|
38400 | 3900 | 12-23-2006
|
|
41900 | 4800 | 08-01-2007
|
|
42300 | 5200 | 08-01-2007
|
|
47100 | 4800 | 08-08-2007
|
|
47100 | 5200 | 08-15-2007
|
|
36100 | 3500 | 12-10-2007
|
|
28000 | 4500 | 01-01-2008
|
|
27700 | 4200 | 01-01-2008
|
|
(10 rows)
|
|
|
|
select first_value(salary) over(order by salary range between 1000 preceding and 1000 following),
|
|
lead(salary) over(order by salary range between 1000 preceding and 1000 following),
|
|
nth_value(salary, 1) over(order by salary range between 1000 preceding and 1000 following),
|
|
salary from empsalary;
|
|
first_value | lead | nth_value | salary
|
|
-------------+------+-----------+--------
|
|
3500 | 3900 | 3500 | 3500
|
|
3500 | 4200 | 3500 | 3900
|
|
3500 | 4500 | 3500 | 4200
|
|
3500 | 4800 | 3500 | 4500
|
|
3900 | 4800 | 3900 | 4800
|
|
3900 | 5000 | 3900 | 4800
|
|
4200 | 5200 | 4200 | 5000
|
|
4200 | 5200 | 4200 | 5200
|
|
4200 | 6000 | 4200 | 5200
|
|
5000 | | 5000 | 6000
|
|
(10 rows)
|
|
|
|
select last_value(salary) over(order by salary range between 1000 preceding and 1000 following),
|
|
lag(salary) over(order by salary range between 1000 preceding and 1000 following),
|
|
salary from empsalary;
|
|
last_value | lag | salary
|
|
------------+------+--------
|
|
4500 | | 3500
|
|
4800 | 3500 | 3900
|
|
5200 | 3900 | 4200
|
|
5200 | 4200 | 4500
|
|
5200 | 4500 | 4800
|
|
5200 | 4800 | 4800
|
|
6000 | 4800 | 5000
|
|
6000 | 5000 | 5200
|
|
6000 | 5200 | 5200
|
|
6000 | 5200 | 6000
|
|
(10 rows)
|
|
|
|
select first_value(salary) over(order by salary range between 1000 following and 3000 following
|
|
exclude current row),
|
|
lead(salary) over(order by salary range between 1000 following and 3000 following exclude ties),
|
|
nth_value(salary, 1) over(order by salary range between 1000 following and 3000 following
|
|
exclude ties),
|
|
salary from empsalary;
|
|
first_value | lead | nth_value | salary
|
|
-------------+------+-----------+--------
|
|
4500 | 3900 | 4500 | 3500
|
|
5000 | 4200 | 5000 | 3900
|
|
5200 | 4500 | 5200 | 4200
|
|
6000 | 4800 | 6000 | 4500
|
|
6000 | 4800 | 6000 | 4800
|
|
6000 | 5000 | 6000 | 4800
|
|
6000 | 5200 | 6000 | 5000
|
|
| 5200 | | 5200
|
|
| 6000 | | 5200
|
|
| | | 6000
|
|
(10 rows)
|
|
|
|
select last_value(salary) over(order by salary range between 1000 following and 3000 following
|
|
exclude group),
|
|
lag(salary) over(order by salary range between 1000 following and 3000 following exclude group),
|
|
salary from empsalary;
|
|
last_value | lag | salary
|
|
------------+------+--------
|
|
6000 | | 3500
|
|
6000 | 3500 | 3900
|
|
6000 | 3900 | 4200
|
|
6000 | 4200 | 4500
|
|
6000 | 4500 | 4800
|
|
6000 | 4800 | 4800
|
|
6000 | 4800 | 5000
|
|
| 5000 | 5200
|
|
| 5200 | 5200
|
|
| 5200 | 6000
|
|
(10 rows)
|
|
|
|
select first_value(salary) over(order by enroll_date range between unbounded preceding and '1 year'::interval following
|
|
exclude ties),
|
|
last_value(salary) over(order by enroll_date range between unbounded preceding and '1 year'::interval following),
|
|
salary, enroll_date from empsalary;
|
|
first_value | last_value | salary | enroll_date
|
|
-------------+------------+--------+-------------
|
|
5000 | 5200 | 5000 | 10-01-2006
|
|
6000 | 5200 | 6000 | 10-01-2006
|
|
5000 | 3500 | 3900 | 12-23-2006
|
|
5000 | 4200 | 4800 | 08-01-2007
|
|
5000 | 4200 | 5200 | 08-01-2007
|
|
5000 | 4200 | 4800 | 08-08-2007
|
|
5000 | 4200 | 5200 | 08-15-2007
|
|
5000 | 4200 | 3500 | 12-10-2007
|
|
5000 | 4200 | 4500 | 01-01-2008
|
|
5000 | 4200 | 4200 | 01-01-2008
|
|
(10 rows)
|
|
|
|
select first_value(salary) over(order by enroll_date range between unbounded preceding and '1 year'::interval following
|
|
exclude ties),
|
|
last_value(salary) over(order by enroll_date range between unbounded preceding and '1 year'::interval following
|
|
exclude ties),
|
|
salary, enroll_date from empsalary;
|
|
first_value | last_value | salary | enroll_date
|
|
-------------+------------+--------+-------------
|
|
5000 | 5200 | 5000 | 10-01-2006
|
|
6000 | 5200 | 6000 | 10-01-2006
|
|
5000 | 3500 | 3900 | 12-23-2006
|
|
5000 | 4200 | 4800 | 08-01-2007
|
|
5000 | 4200 | 5200 | 08-01-2007
|
|
5000 | 4200 | 4800 | 08-08-2007
|
|
5000 | 4200 | 5200 | 08-15-2007
|
|
5000 | 4200 | 3500 | 12-10-2007
|
|
5000 | 4500 | 4500 | 01-01-2008
|
|
5000 | 4200 | 4200 | 01-01-2008
|
|
(10 rows)
|
|
|
|
select first_value(salary) over(order by enroll_date range between unbounded preceding and '1 year'::interval following
|
|
exclude group),
|
|
last_value(salary) over(order by enroll_date range between unbounded preceding and '1 year'::interval following
|
|
exclude group),
|
|
salary, enroll_date from empsalary;
|
|
first_value | last_value | salary | enroll_date
|
|
-------------+------------+--------+-------------
|
|
3900 | 5200 | 5000 | 10-01-2006
|
|
3900 | 5200 | 6000 | 10-01-2006
|
|
5000 | 3500 | 3900 | 12-23-2006
|
|
5000 | 4200 | 4800 | 08-01-2007
|
|
5000 | 4200 | 5200 | 08-01-2007
|
|
5000 | 4200 | 4800 | 08-08-2007
|
|
5000 | 4200 | 5200 | 08-15-2007
|
|
5000 | 4200 | 3500 | 12-10-2007
|
|
5000 | 3500 | 4500 | 01-01-2008
|
|
5000 | 3500 | 4200 | 01-01-2008
|
|
(10 rows)
|
|
|
|
select first_value(salary) over(order by enroll_date range between unbounded preceding and '1 year'::interval following
|
|
exclude current row),
|
|
last_value(salary) over(order by enroll_date range between unbounded preceding and '1 year'::interval following
|
|
exclude current row),
|
|
salary, enroll_date from empsalary;
|
|
first_value | last_value | salary | enroll_date
|
|
-------------+------------+--------+-------------
|
|
6000 | 5200 | 5000 | 10-01-2006
|
|
5000 | 5200 | 6000 | 10-01-2006
|
|
5000 | 3500 | 3900 | 12-23-2006
|
|
5000 | 4200 | 4800 | 08-01-2007
|
|
5000 | 4200 | 5200 | 08-01-2007
|
|
5000 | 4200 | 4800 | 08-08-2007
|
|
5000 | 4200 | 5200 | 08-15-2007
|
|
5000 | 4200 | 3500 | 12-10-2007
|
|
5000 | 4200 | 4500 | 01-01-2008
|
|
5000 | 4500 | 4200 | 01-01-2008
|
|
(10 rows)
|
|
|
|
-- RANGE offset PRECEDING/FOLLOWING with null values
|
|
select x, y,
|
|
first_value(y) over w,
|
|
last_value(y) over w
|
|
from
|
|
(select x, x as y from generate_series(1,5) as x
|
|
union all select null, 42
|
|
union all select null, 43) ss
|
|
window w as
|
|
(order by x asc nulls first range between 2 preceding and 2 following);
|
|
x | y | first_value | last_value
|
|
---+----+-------------+------------
|
|
| 42 | 42 | 43
|
|
| 43 | 42 | 43
|
|
1 | 1 | 1 | 3
|
|
2 | 2 | 1 | 4
|
|
3 | 3 | 1 | 5
|
|
4 | 4 | 2 | 5
|
|
5 | 5 | 3 | 5
|
|
(7 rows)
|
|
|
|
select x, y,
|
|
first_value(y) over w,
|
|
last_value(y) over w
|
|
from
|
|
(select x, x as y from generate_series(1,5) as x
|
|
union all select null, 42
|
|
union all select null, 43) ss
|
|
window w as
|
|
(order by x asc nulls last range between 2 preceding and 2 following);
|
|
x | y | first_value | last_value
|
|
---+----+-------------+------------
|
|
1 | 1 | 1 | 3
|
|
2 | 2 | 1 | 4
|
|
3 | 3 | 1 | 5
|
|
4 | 4 | 2 | 5
|
|
5 | 5 | 3 | 5
|
|
| 42 | 42 | 43
|
|
| 43 | 42 | 43
|
|
(7 rows)
|
|
|
|
select x, y,
|
|
first_value(y) over w,
|
|
last_value(y) over w
|
|
from
|
|
(select x, x as y from generate_series(1,5) as x
|
|
union all select null, 42
|
|
union all select null, 43) ss
|
|
window w as
|
|
(order by x desc nulls first range between 2 preceding and 2 following);
|
|
x | y | first_value | last_value
|
|
---+----+-------------+------------
|
|
| 43 | 43 | 42
|
|
| 42 | 43 | 42
|
|
5 | 5 | 5 | 3
|
|
4 | 4 | 5 | 2
|
|
3 | 3 | 5 | 1
|
|
2 | 2 | 4 | 1
|
|
1 | 1 | 3 | 1
|
|
(7 rows)
|
|
|
|
select x, y,
|
|
first_value(y) over w,
|
|
last_value(y) over w
|
|
from
|
|
(select x, x as y from generate_series(1,5) as x
|
|
union all select null, 42
|
|
union all select null, 43) ss
|
|
window w as
|
|
(order by x desc nulls last range between 2 preceding and 2 following);
|
|
x | y | first_value | last_value
|
|
---+----+-------------+------------
|
|
5 | 5 | 5 | 3
|
|
4 | 4 | 5 | 2
|
|
3 | 3 | 5 | 1
|
|
2 | 2 | 4 | 1
|
|
1 | 1 | 3 | 1
|
|
| 42 | 42 | 43
|
|
| 43 | 42 | 43
|
|
(7 rows)
|
|
|
|
-- Check overflow behavior for various integer sizes
|
|
select x, last_value(x) over (order by x::smallint range between current row and 2147450884 following)
|
|
from generate_series(32764, 32766) x;
|
|
x | last_value
|
|
-------+------------
|
|
32764 | 32766
|
|
32765 | 32766
|
|
32766 | 32766
|
|
(3 rows)
|
|
|
|
select x, last_value(x) over (order by x::smallint desc range between current row and 2147450885 following)
|
|
from generate_series(-32766, -32764) x;
|
|
x | last_value
|
|
--------+------------
|
|
-32764 | -32766
|
|
-32765 | -32766
|
|
-32766 | -32766
|
|
(3 rows)
|
|
|
|
select x, last_value(x) over (order by x range between current row and 4 following)
|
|
from generate_series(2147483644, 2147483646) x;
|
|
x | last_value
|
|
------------+------------
|
|
2147483644 | 2147483646
|
|
2147483645 | 2147483646
|
|
2147483646 | 2147483646
|
|
(3 rows)
|
|
|
|
select x, last_value(x) over (order by x desc range between current row and 5 following)
|
|
from generate_series(-2147483646, -2147483644) x;
|
|
x | last_value
|
|
-------------+-------------
|
|
-2147483644 | -2147483646
|
|
-2147483645 | -2147483646
|
|
-2147483646 | -2147483646
|
|
(3 rows)
|
|
|
|
select x, last_value(x) over (order by x range between current row and 4 following)
|
|
from generate_series(9223372036854775804, 9223372036854775806) x;
|
|
x | last_value
|
|
---------------------+---------------------
|
|
9223372036854775804 | 9223372036854775806
|
|
9223372036854775805 | 9223372036854775806
|
|
9223372036854775806 | 9223372036854775806
|
|
(3 rows)
|
|
|
|
select x, last_value(x) over (order by x desc range between current row and 5 following)
|
|
from generate_series(-9223372036854775806, -9223372036854775804) x;
|
|
x | last_value
|
|
----------------------+----------------------
|
|
-9223372036854775804 | -9223372036854775806
|
|
-9223372036854775805 | -9223372036854775806
|
|
-9223372036854775806 | -9223372036854775806
|
|
(3 rows)
|
|
|
|
-- Test in_range for other numeric datatypes
|
|
create temp table numerics(
|
|
id int,
|
|
f_float4 float4,
|
|
f_float8 float8,
|
|
f_numeric numeric
|
|
);
|
|
insert into numerics values
|
|
(0, '-infinity', '-infinity', '-1000'), -- numeric type lacks infinities
|
|
(1, -3, -3, -3),
|
|
(2, -1, -1, -1),
|
|
(3, 0, 0, 0),
|
|
(4, 1.1, 1.1, 1.1),
|
|
(5, 1.12, 1.12, 1.12),
|
|
(6, 2, 2, 2),
|
|
(7, 100, 100, 100),
|
|
(8, 'infinity', 'infinity', '1000'),
|
|
(9, 'NaN', 'NaN', 'NaN');
|
|
select id, f_float4, first_value(id) over w, last_value(id) over w
|
|
from numerics
|
|
window w as (order by f_float4 range between
|
|
1 preceding and 1 following);
|
|
id | f_float4 | first_value | last_value
|
|
----+-----------+-------------+------------
|
|
0 | -Infinity | 0 | 0
|
|
1 | -3 | 1 | 1
|
|
2 | -1 | 2 | 3
|
|
3 | 0 | 2 | 3
|
|
4 | 1.1 | 4 | 6
|
|
5 | 1.12 | 4 | 6
|
|
6 | 2 | 4 | 6
|
|
7 | 100 | 7 | 7
|
|
8 | Infinity | 8 | 8
|
|
9 | NaN | 9 | 9
|
|
(10 rows)
|
|
|
|
select id, f_float4, first_value(id) over w, last_value(id) over w
|
|
from numerics
|
|
window w as (order by f_float4 range between
|
|
1 preceding and 1.1::float4 following);
|
|
id | f_float4 | first_value | last_value
|
|
----+-----------+-------------+------------
|
|
0 | -Infinity | 0 | 0
|
|
1 | -3 | 1 | 1
|
|
2 | -1 | 2 | 3
|
|
3 | 0 | 2 | 4
|
|
4 | 1.1 | 4 | 6
|
|
5 | 1.12 | 4 | 6
|
|
6 | 2 | 4 | 6
|
|
7 | 100 | 7 | 7
|
|
8 | Infinity | 8 | 8
|
|
9 | NaN | 9 | 9
|
|
(10 rows)
|
|
|
|
select id, f_float4, first_value(id) over w, last_value(id) over w
|
|
from numerics
|
|
window w as (order by f_float4 range between
|
|
'inf' preceding and 'inf' following);
|
|
id | f_float4 | first_value | last_value
|
|
----+-----------+-------------+------------
|
|
0 | -Infinity | 0 | 8
|
|
1 | -3 | 0 | 8
|
|
2 | -1 | 0 | 8
|
|
3 | 0 | 0 | 8
|
|
4 | 1.1 | 0 | 8
|
|
5 | 1.12 | 0 | 8
|
|
6 | 2 | 0 | 8
|
|
7 | 100 | 0 | 8
|
|
8 | Infinity | 0 | 8
|
|
9 | NaN | 9 | 9
|
|
(10 rows)
|
|
|
|
select id, f_float4, first_value(id) over w, last_value(id) over w
|
|
from numerics
|
|
window w as (order by f_float4 range between
|
|
1.1 preceding and 'NaN' following); -- error, NaN disallowed
|
|
ERROR: invalid preceding or following size in window function
|
|
select id, f_float8, first_value(id) over w, last_value(id) over w
|
|
from numerics
|
|
window w as (order by f_float8 range between
|
|
1 preceding and 1 following);
|
|
id | f_float8 | first_value | last_value
|
|
----+-----------+-------------+------------
|
|
0 | -Infinity | 0 | 0
|
|
1 | -3 | 1 | 1
|
|
2 | -1 | 2 | 3
|
|
3 | 0 | 2 | 3
|
|
4 | 1.1 | 4 | 6
|
|
5 | 1.12 | 4 | 6
|
|
6 | 2 | 4 | 6
|
|
7 | 100 | 7 | 7
|
|
8 | Infinity | 8 | 8
|
|
9 | NaN | 9 | 9
|
|
(10 rows)
|
|
|
|
select id, f_float8, first_value(id) over w, last_value(id) over w
|
|
from numerics
|
|
window w as (order by f_float8 range between
|
|
1 preceding and 1.1::float8 following);
|
|
id | f_float8 | first_value | last_value
|
|
----+-----------+-------------+------------
|
|
0 | -Infinity | 0 | 0
|
|
1 | -3 | 1 | 1
|
|
2 | -1 | 2 | 3
|
|
3 | 0 | 2 | 4
|
|
4 | 1.1 | 4 | 6
|
|
5 | 1.12 | 4 | 6
|
|
6 | 2 | 4 | 6
|
|
7 | 100 | 7 | 7
|
|
8 | Infinity | 8 | 8
|
|
9 | NaN | 9 | 9
|
|
(10 rows)
|
|
|
|
select id, f_float8, first_value(id) over w, last_value(id) over w
|
|
from numerics
|
|
window w as (order by f_float8 range between
|
|
'inf' preceding and 'inf' following);
|
|
id | f_float8 | first_value | last_value
|
|
----+-----------+-------------+------------
|
|
0 | -Infinity | 0 | 8
|
|
1 | -3 | 0 | 8
|
|
2 | -1 | 0 | 8
|
|
3 | 0 | 0 | 8
|
|
4 | 1.1 | 0 | 8
|
|
5 | 1.12 | 0 | 8
|
|
6 | 2 | 0 | 8
|
|
7 | 100 | 0 | 8
|
|
8 | Infinity | 0 | 8
|
|
9 | NaN | 9 | 9
|
|
(10 rows)
|
|
|
|
select id, f_float8, first_value(id) over w, last_value(id) over w
|
|
from numerics
|
|
window w as (order by f_float8 range between
|
|
1.1 preceding and 'NaN' following); -- error, NaN disallowed
|
|
ERROR: invalid preceding or following size in window function
|
|
select id, f_numeric, first_value(id) over w, last_value(id) over w
|
|
from numerics
|
|
window w as (order by f_numeric range between
|
|
1 preceding and 1 following);
|
|
id | f_numeric | first_value | last_value
|
|
----+-----------+-------------+------------
|
|
0 | -1000 | 0 | 0
|
|
1 | -3 | 1 | 1
|
|
2 | -1 | 2 | 3
|
|
3 | 0 | 2 | 3
|
|
4 | 1.1 | 4 | 6
|
|
5 | 1.12 | 4 | 6
|
|
6 | 2 | 4 | 6
|
|
7 | 100 | 7 | 7
|
|
8 | 1000 | 8 | 8
|
|
9 | NaN | 9 | 9
|
|
(10 rows)
|
|
|
|
select id, f_numeric, first_value(id) over w, last_value(id) over w
|
|
from numerics
|
|
window w as (order by f_numeric range between
|
|
1 preceding and 1.1::numeric following);
|
|
id | f_numeric | first_value | last_value
|
|
----+-----------+-------------+------------
|
|
0 | -1000 | 0 | 0
|
|
1 | -3 | 1 | 1
|
|
2 | -1 | 2 | 3
|
|
3 | 0 | 2 | 4
|
|
4 | 1.1 | 4 | 6
|
|
5 | 1.12 | 4 | 6
|
|
6 | 2 | 4 | 6
|
|
7 | 100 | 7 | 7
|
|
8 | 1000 | 8 | 8
|
|
9 | NaN | 9 | 9
|
|
(10 rows)
|
|
|
|
select id, f_numeric, first_value(id) over w, last_value(id) over w
|
|
from numerics
|
|
window w as (order by f_numeric range between
|
|
1 preceding and 1.1::float8 following); -- currently unsupported
|
|
ERROR: RANGE with offset PRECEDING/FOLLOWING is not supported for column type numeric and offset type double precision
|
|
LINE 4: 1 preceding and 1.1::float8 following);
|
|
^
|
|
HINT: Cast the offset value to an appropriate type.
|
|
select id, f_numeric, first_value(id) over w, last_value(id) over w
|
|
from numerics
|
|
window w as (order by f_numeric range between
|
|
1.1 preceding and 'NaN' following); -- error, NaN disallowed
|
|
ERROR: invalid preceding or following size in window function
|
|
-- Test in_range for other datetime datatypes
|
|
create temp table datetimes(
|
|
id int,
|
|
f_time time,
|
|
f_timetz timetz,
|
|
f_interval interval,
|
|
f_timestamptz timestamptz,
|
|
f_timestamp timestamp
|
|
);
|
|
insert into datetimes values
|
|
(1, '11:00', '11:00 BST', '1 year', '2000-10-19 10:23:54+01', '2000-10-19 10:23:54'),
|
|
(2, '12:00', '12:00 BST', '2 years', '2001-10-19 10:23:54+01', '2001-10-19 10:23:54'),
|
|
(3, '13:00', '13:00 BST', '3 years', '2001-10-19 10:23:54+01', '2001-10-19 10:23:54'),
|
|
(4, '14:00', '14:00 BST', '4 years', '2002-10-19 10:23:54+01', '2002-10-19 10:23:54'),
|
|
(5, '15:00', '15:00 BST', '5 years', '2003-10-19 10:23:54+01', '2003-10-19 10:23:54'),
|
|
(6, '15:00', '15:00 BST', '5 years', '2004-10-19 10:23:54+01', '2004-10-19 10:23:54'),
|
|
(7, '17:00', '17:00 BST', '7 years', '2005-10-19 10:23:54+01', '2005-10-19 10:23:54'),
|
|
(8, '18:00', '18:00 BST', '8 years', '2006-10-19 10:23:54+01', '2006-10-19 10:23:54'),
|
|
(9, '19:00', '19:00 BST', '9 years', '2007-10-19 10:23:54+01', '2007-10-19 10:23:54'),
|
|
(10, '20:00', '20:00 BST', '10 years', '2008-10-19 10:23:54+01', '2008-10-19 10:23:54');
|
|
select id, f_time, first_value(id) over w, last_value(id) over w
|
|
from datetimes
|
|
window w as (order by f_time range between
|
|
'70 min'::interval preceding and '2 hours'::interval following);
|
|
id | f_time | first_value | last_value
|
|
----+----------+-------------+------------
|
|
1 | 11:00:00 | 1 | 3
|
|
2 | 12:00:00 | 1 | 4
|
|
3 | 13:00:00 | 2 | 6
|
|
4 | 14:00:00 | 3 | 6
|
|
5 | 15:00:00 | 4 | 7
|
|
6 | 15:00:00 | 4 | 7
|
|
7 | 17:00:00 | 7 | 9
|
|
8 | 18:00:00 | 7 | 10
|
|
9 | 19:00:00 | 8 | 10
|
|
10 | 20:00:00 | 9 | 10
|
|
(10 rows)
|
|
|
|
select id, f_time, first_value(id) over w, last_value(id) over w
|
|
from datetimes
|
|
window w as (order by f_time desc range between
|
|
'70 min' preceding and '2 hours' following);
|
|
id | f_time | first_value | last_value
|
|
----+----------+-------------+------------
|
|
10 | 20:00:00 | 10 | 8
|
|
9 | 19:00:00 | 10 | 7
|
|
8 | 18:00:00 | 9 | 7
|
|
7 | 17:00:00 | 8 | 5
|
|
6 | 15:00:00 | 6 | 3
|
|
5 | 15:00:00 | 6 | 3
|
|
4 | 14:00:00 | 6 | 2
|
|
3 | 13:00:00 | 4 | 1
|
|
2 | 12:00:00 | 3 | 1
|
|
1 | 11:00:00 | 2 | 1
|
|
(10 rows)
|
|
|
|
select id, f_timetz, first_value(id) over w, last_value(id) over w
|
|
from datetimes
|
|
window w as (order by f_timetz range between
|
|
'70 min'::interval preceding and '2 hours'::interval following);
|
|
id | f_timetz | first_value | last_value
|
|
----+-------------+-------------+------------
|
|
1 | 11:00:00+01 | 1 | 3
|
|
2 | 12:00:00+01 | 1 | 4
|
|
3 | 13:00:00+01 | 2 | 6
|
|
4 | 14:00:00+01 | 3 | 6
|
|
5 | 15:00:00+01 | 4 | 7
|
|
6 | 15:00:00+01 | 4 | 7
|
|
7 | 17:00:00+01 | 7 | 9
|
|
8 | 18:00:00+01 | 7 | 10
|
|
9 | 19:00:00+01 | 8 | 10
|
|
10 | 20:00:00+01 | 9 | 10
|
|
(10 rows)
|
|
|
|
select id, f_timetz, first_value(id) over w, last_value(id) over w
|
|
from datetimes
|
|
window w as (order by f_timetz desc range between
|
|
'70 min' preceding and '2 hours' following);
|
|
id | f_timetz | first_value | last_value
|
|
----+-------------+-------------+------------
|
|
10 | 20:00:00+01 | 10 | 8
|
|
9 | 19:00:00+01 | 10 | 7
|
|
8 | 18:00:00+01 | 9 | 7
|
|
7 | 17:00:00+01 | 8 | 5
|
|
6 | 15:00:00+01 | 6 | 3
|
|
5 | 15:00:00+01 | 6 | 3
|
|
4 | 14:00:00+01 | 6 | 2
|
|
3 | 13:00:00+01 | 4 | 1
|
|
2 | 12:00:00+01 | 3 | 1
|
|
1 | 11:00:00+01 | 2 | 1
|
|
(10 rows)
|
|
|
|
select id, f_interval, first_value(id) over w, last_value(id) over w
|
|
from datetimes
|
|
window w as (order by f_interval range between
|
|
'1 year'::interval preceding and '1 year'::interval following);
|
|
id | f_interval | first_value | last_value
|
|
----+------------+-------------+------------
|
|
1 | @ 1 year | 1 | 2
|
|
2 | @ 2 years | 1 | 3
|
|
3 | @ 3 years | 2 | 4
|
|
4 | @ 4 years | 3 | 6
|
|
5 | @ 5 years | 4 | 6
|
|
6 | @ 5 years | 4 | 6
|
|
7 | @ 7 years | 7 | 8
|
|
8 | @ 8 years | 7 | 9
|
|
9 | @ 9 years | 8 | 10
|
|
10 | @ 10 years | 9 | 10
|
|
(10 rows)
|
|
|
|
select id, f_interval, first_value(id) over w, last_value(id) over w
|
|
from datetimes
|
|
window w as (order by f_interval desc range between
|
|
'1 year' preceding and '1 year' following);
|
|
id | f_interval | first_value | last_value
|
|
----+------------+-------------+------------
|
|
10 | @ 10 years | 10 | 9
|
|
9 | @ 9 years | 10 | 8
|
|
8 | @ 8 years | 9 | 7
|
|
7 | @ 7 years | 8 | 7
|
|
6 | @ 5 years | 6 | 4
|
|
5 | @ 5 years | 6 | 4
|
|
4 | @ 4 years | 6 | 3
|
|
3 | @ 3 years | 4 | 2
|
|
2 | @ 2 years | 3 | 1
|
|
1 | @ 1 year | 2 | 1
|
|
(10 rows)
|
|
|
|
select id, f_timestamptz, first_value(id) over w, last_value(id) over w
|
|
from datetimes
|
|
window w as (order by f_timestamptz range between
|
|
'1 year'::interval preceding and '1 year'::interval following);
|
|
id | f_timestamptz | first_value | last_value
|
|
----+------------------------------+-------------+------------
|
|
1 | Thu Oct 19 02:23:54 2000 PDT | 1 | 3
|
|
2 | Fri Oct 19 02:23:54 2001 PDT | 1 | 4
|
|
3 | Fri Oct 19 02:23:54 2001 PDT | 1 | 4
|
|
4 | Sat Oct 19 02:23:54 2002 PDT | 2 | 5
|
|
5 | Sun Oct 19 02:23:54 2003 PDT | 4 | 6
|
|
6 | Tue Oct 19 02:23:54 2004 PDT | 5 | 7
|
|
7 | Wed Oct 19 02:23:54 2005 PDT | 6 | 8
|
|
8 | Thu Oct 19 02:23:54 2006 PDT | 7 | 9
|
|
9 | Fri Oct 19 02:23:54 2007 PDT | 8 | 10
|
|
10 | Sun Oct 19 02:23:54 2008 PDT | 9 | 10
|
|
(10 rows)
|
|
|
|
select id, f_timestamptz, first_value(id) over w, last_value(id) over w
|
|
from datetimes
|
|
window w as (order by f_timestamptz desc range between
|
|
'1 year' preceding and '1 year' following);
|
|
id | f_timestamptz | first_value | last_value
|
|
----+------------------------------+-------------+------------
|
|
10 | Sun Oct 19 02:23:54 2008 PDT | 10 | 9
|
|
9 | Fri Oct 19 02:23:54 2007 PDT | 10 | 8
|
|
8 | Thu Oct 19 02:23:54 2006 PDT | 9 | 7
|
|
7 | Wed Oct 19 02:23:54 2005 PDT | 8 | 6
|
|
6 | Tue Oct 19 02:23:54 2004 PDT | 7 | 5
|
|
5 | Sun Oct 19 02:23:54 2003 PDT | 6 | 4
|
|
4 | Sat Oct 19 02:23:54 2002 PDT | 5 | 2
|
|
3 | Fri Oct 19 02:23:54 2001 PDT | 4 | 1
|
|
2 | Fri Oct 19 02:23:54 2001 PDT | 4 | 1
|
|
1 | Thu Oct 19 02:23:54 2000 PDT | 3 | 1
|
|
(10 rows)
|
|
|
|
select id, f_timestamp, first_value(id) over w, last_value(id) over w
|
|
from datetimes
|
|
window w as (order by f_timestamp range between
|
|
'1 year'::interval preceding and '1 year'::interval following);
|
|
id | f_timestamp | first_value | last_value
|
|
----+--------------------------+-------------+------------
|
|
1 | Thu Oct 19 10:23:54 2000 | 1 | 3
|
|
2 | Fri Oct 19 10:23:54 2001 | 1 | 4
|
|
3 | Fri Oct 19 10:23:54 2001 | 1 | 4
|
|
4 | Sat Oct 19 10:23:54 2002 | 2 | 5
|
|
5 | Sun Oct 19 10:23:54 2003 | 4 | 6
|
|
6 | Tue Oct 19 10:23:54 2004 | 5 | 7
|
|
7 | Wed Oct 19 10:23:54 2005 | 6 | 8
|
|
8 | Thu Oct 19 10:23:54 2006 | 7 | 9
|
|
9 | Fri Oct 19 10:23:54 2007 | 8 | 10
|
|
10 | Sun Oct 19 10:23:54 2008 | 9 | 10
|
|
(10 rows)
|
|
|
|
select id, f_timestamp, first_value(id) over w, last_value(id) over w
|
|
from datetimes
|
|
window w as (order by f_timestamp desc range between
|
|
'1 year' preceding and '1 year' following);
|
|
id | f_timestamp | first_value | last_value
|
|
----+--------------------------+-------------+------------
|
|
10 | Sun Oct 19 10:23:54 2008 | 10 | 9
|
|
9 | Fri Oct 19 10:23:54 2007 | 10 | 8
|
|
8 | Thu Oct 19 10:23:54 2006 | 9 | 7
|
|
7 | Wed Oct 19 10:23:54 2005 | 8 | 6
|
|
6 | Tue Oct 19 10:23:54 2004 | 7 | 5
|
|
5 | Sun Oct 19 10:23:54 2003 | 6 | 4
|
|
4 | Sat Oct 19 10:23:54 2002 | 5 | 2
|
|
3 | Fri Oct 19 10:23:54 2001 | 4 | 1
|
|
2 | Fri Oct 19 10:23:54 2001 | 4 | 1
|
|
1 | Thu Oct 19 10:23:54 2000 | 3 | 1
|
|
(10 rows)
|
|
|
|
-- RANGE offset PRECEDING/FOLLOWING error cases
|
|
select sum(salary) over (order by enroll_date, salary range between '1 year'::interval preceding and '2 years'::interval following
|
|
exclude ties), salary, enroll_date from empsalary;
|
|
ERROR: RANGE with offset PRECEDING/FOLLOWING requires exactly one ORDER BY column
|
|
LINE 1: select sum(salary) over (order by enroll_date, salary range ...
|
|
^
|
|
select sum(salary) over (range between '1 year'::interval preceding and '2 years'::interval following
|
|
exclude ties), salary, enroll_date from empsalary;
|
|
ERROR: RANGE with offset PRECEDING/FOLLOWING requires exactly one ORDER BY column
|
|
LINE 1: select sum(salary) over (range between '1 year'::interval pr...
|
|
^
|
|
select sum(salary) over (order by depname range between '1 year'::interval preceding and '2 years'::interval following
|
|
exclude ties), salary, enroll_date from empsalary;
|
|
ERROR: RANGE with offset PRECEDING/FOLLOWING is not supported for column type text
|
|
LINE 1: ... sum(salary) over (order by depname range between '1 year'::...
|
|
^
|
|
select max(enroll_date) over (order by enroll_date range between 1 preceding and 2 following
|
|
exclude ties), salary, enroll_date from empsalary;
|
|
ERROR: RANGE with offset PRECEDING/FOLLOWING is not supported for column type date and offset type integer
|
|
LINE 1: ...ll_date) over (order by enroll_date range between 1 precedin...
|
|
^
|
|
HINT: Cast the offset value to an appropriate type.
|
|
select max(enroll_date) over (order by salary range between -1 preceding and 2 following
|
|
exclude ties), salary, enroll_date from empsalary;
|
|
ERROR: invalid preceding or following size in window function
|
|
select max(enroll_date) over (order by salary range between 1 preceding and -2 following
|
|
exclude ties), salary, enroll_date from empsalary;
|
|
ERROR: invalid preceding or following size in window function
|
|
select max(enroll_date) over (order by salary range between '1 year'::interval preceding and '2 years'::interval following
|
|
exclude ties), salary, enroll_date from empsalary;
|
|
ERROR: RANGE with offset PRECEDING/FOLLOWING is not supported for column type integer and offset type interval
|
|
LINE 1: ...(enroll_date) over (order by salary range between '1 year'::...
|
|
^
|
|
HINT: Cast the offset value to an appropriate type.
|
|
select max(enroll_date) over (order by enroll_date range between '1 year'::interval preceding and '-2 years'::interval following
|
|
exclude ties), salary, enroll_date from empsalary;
|
|
ERROR: invalid preceding or following size in window function
|
|
-- GROUPS tests
|
|
SELECT sum(unique1) over (order by four groups between unbounded preceding and current row),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
12 | 0 | 0
|
|
12 | 8 | 0
|
|
12 | 4 | 0
|
|
27 | 5 | 1
|
|
27 | 9 | 1
|
|
27 | 1 | 1
|
|
35 | 6 | 2
|
|
35 | 2 | 2
|
|
45 | 3 | 3
|
|
45 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (order by four groups between unbounded preceding and unbounded following),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
45 | 0 | 0
|
|
45 | 8 | 0
|
|
45 | 4 | 0
|
|
45 | 5 | 1
|
|
45 | 9 | 1
|
|
45 | 1 | 1
|
|
45 | 6 | 2
|
|
45 | 2 | 2
|
|
45 | 3 | 3
|
|
45 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (order by four groups between current row and unbounded following),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
45 | 0 | 0
|
|
45 | 8 | 0
|
|
45 | 4 | 0
|
|
33 | 5 | 1
|
|
33 | 9 | 1
|
|
33 | 1 | 1
|
|
18 | 6 | 2
|
|
18 | 2 | 2
|
|
10 | 3 | 3
|
|
10 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (order by four groups between 1 preceding and unbounded following),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
45 | 0 | 0
|
|
45 | 8 | 0
|
|
45 | 4 | 0
|
|
45 | 5 | 1
|
|
45 | 9 | 1
|
|
45 | 1 | 1
|
|
33 | 6 | 2
|
|
33 | 2 | 2
|
|
18 | 3 | 3
|
|
18 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (order by four groups between 1 following and unbounded following),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
33 | 0 | 0
|
|
33 | 8 | 0
|
|
33 | 4 | 0
|
|
18 | 5 | 1
|
|
18 | 9 | 1
|
|
18 | 1 | 1
|
|
10 | 6 | 2
|
|
10 | 2 | 2
|
|
| 3 | 3
|
|
| 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (order by four groups between unbounded preceding and 2 following),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
35 | 0 | 0
|
|
35 | 8 | 0
|
|
35 | 4 | 0
|
|
45 | 5 | 1
|
|
45 | 9 | 1
|
|
45 | 1 | 1
|
|
45 | 6 | 2
|
|
45 | 2 | 2
|
|
45 | 3 | 3
|
|
45 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (order by four groups between 2 preceding and 1 preceding),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
| 0 | 0
|
|
| 8 | 0
|
|
| 4 | 0
|
|
12 | 5 | 1
|
|
12 | 9 | 1
|
|
12 | 1 | 1
|
|
27 | 6 | 2
|
|
27 | 2 | 2
|
|
23 | 3 | 3
|
|
23 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (order by four groups between 2 preceding and 1 following),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
27 | 0 | 0
|
|
27 | 8 | 0
|
|
27 | 4 | 0
|
|
35 | 5 | 1
|
|
35 | 9 | 1
|
|
35 | 1 | 1
|
|
45 | 6 | 2
|
|
45 | 2 | 2
|
|
33 | 3 | 3
|
|
33 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (order by four groups between 0 preceding and 0 following),
|
|
unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
12 | 0 | 0
|
|
12 | 8 | 0
|
|
12 | 4 | 0
|
|
15 | 5 | 1
|
|
15 | 9 | 1
|
|
15 | 1 | 1
|
|
8 | 6 | 2
|
|
8 | 2 | 2
|
|
10 | 3 | 3
|
|
10 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (order by four groups between 2 preceding and 1 following
|
|
exclude current row), unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
27 | 0 | 0
|
|
19 | 8 | 0
|
|
23 | 4 | 0
|
|
30 | 5 | 1
|
|
26 | 9 | 1
|
|
34 | 1 | 1
|
|
39 | 6 | 2
|
|
43 | 2 | 2
|
|
30 | 3 | 3
|
|
26 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (order by four groups between 2 preceding and 1 following
|
|
exclude group), unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
15 | 0 | 0
|
|
15 | 8 | 0
|
|
15 | 4 | 0
|
|
20 | 5 | 1
|
|
20 | 9 | 1
|
|
20 | 1 | 1
|
|
37 | 6 | 2
|
|
37 | 2 | 2
|
|
23 | 3 | 3
|
|
23 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (order by four groups between 2 preceding and 1 following
|
|
exclude ties), unique1, four
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four
|
|
-----+---------+------
|
|
15 | 0 | 0
|
|
23 | 8 | 0
|
|
19 | 4 | 0
|
|
25 | 5 | 1
|
|
29 | 9 | 1
|
|
21 | 1 | 1
|
|
43 | 6 | 2
|
|
39 | 2 | 2
|
|
26 | 3 | 3
|
|
30 | 7 | 3
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (partition by ten
|
|
order by four groups between 0 preceding and 0 following),unique1, four, ten
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four | ten
|
|
-----+---------+------+-----
|
|
0 | 0 | 0 | 0
|
|
1 | 1 | 1 | 1
|
|
2 | 2 | 2 | 2
|
|
3 | 3 | 3 | 3
|
|
4 | 4 | 0 | 4
|
|
5 | 5 | 1 | 5
|
|
6 | 6 | 2 | 6
|
|
7 | 7 | 3 | 7
|
|
8 | 8 | 0 | 8
|
|
9 | 9 | 1 | 9
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (partition by ten
|
|
order by four groups between 0 preceding and 0 following exclude current row), unique1, four, ten
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four | ten
|
|
-----+---------+------+-----
|
|
| 0 | 0 | 0
|
|
| 1 | 1 | 1
|
|
| 2 | 2 | 2
|
|
| 3 | 3 | 3
|
|
| 4 | 0 | 4
|
|
| 5 | 1 | 5
|
|
| 6 | 2 | 6
|
|
| 7 | 3 | 7
|
|
| 8 | 0 | 8
|
|
| 9 | 1 | 9
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (partition by ten
|
|
order by four groups between 0 preceding and 0 following exclude group), unique1, four, ten
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four | ten
|
|
-----+---------+------+-----
|
|
| 0 | 0 | 0
|
|
| 1 | 1 | 1
|
|
| 2 | 2 | 2
|
|
| 3 | 3 | 3
|
|
| 4 | 0 | 4
|
|
| 5 | 1 | 5
|
|
| 6 | 2 | 6
|
|
| 7 | 3 | 7
|
|
| 8 | 0 | 8
|
|
| 9 | 1 | 9
|
|
(10 rows)
|
|
|
|
SELECT sum(unique1) over (partition by ten
|
|
order by four groups between 0 preceding and 0 following exclude ties), unique1, four, ten
|
|
FROM tenk1 WHERE unique1 < 10;
|
|
sum | unique1 | four | ten
|
|
-----+---------+------+-----
|
|
0 | 0 | 0 | 0
|
|
1 | 1 | 1 | 1
|
|
2 | 2 | 2 | 2
|
|
3 | 3 | 3 | 3
|
|
4 | 4 | 0 | 4
|
|
5 | 5 | 1 | 5
|
|
6 | 6 | 2 | 6
|
|
7 | 7 | 3 | 7
|
|
8 | 8 | 0 | 8
|
|
9 | 9 | 1 | 9
|
|
(10 rows)
|
|
|
|
select first_value(salary) over(order by enroll_date groups between 1 preceding and 1 following),
|
|
lead(salary) over(order by enroll_date groups between 1 preceding and 1 following),
|
|
nth_value(salary, 1) over(order by enroll_date groups between 1 preceding and 1 following),
|
|
salary, enroll_date from empsalary;
|
|
first_value | lead | nth_value | salary | enroll_date
|
|
-------------+------+-----------+--------+-------------
|
|
5000 | 6000 | 5000 | 5000 | 10-01-2006
|
|
5000 | 3900 | 5000 | 6000 | 10-01-2006
|
|
5000 | 4800 | 5000 | 3900 | 12-23-2006
|
|
3900 | 5200 | 3900 | 4800 | 08-01-2007
|
|
3900 | 4800 | 3900 | 5200 | 08-01-2007
|
|
4800 | 5200 | 4800 | 4800 | 08-08-2007
|
|
4800 | 3500 | 4800 | 5200 | 08-15-2007
|
|
5200 | 4500 | 5200 | 3500 | 12-10-2007
|
|
3500 | 4200 | 3500 | 4500 | 01-01-2008
|
|
3500 | | 3500 | 4200 | 01-01-2008
|
|
(10 rows)
|
|
|
|
select last_value(salary) over(order by enroll_date groups between 1 preceding and 1 following),
|
|
lag(salary) over(order by enroll_date groups between 1 preceding and 1 following),
|
|
salary, enroll_date from empsalary;
|
|
last_value | lag | salary | enroll_date
|
|
------------+------+--------+-------------
|
|
3900 | | 5000 | 10-01-2006
|
|
3900 | 5000 | 6000 | 10-01-2006
|
|
5200 | 6000 | 3900 | 12-23-2006
|
|
4800 | 3900 | 4800 | 08-01-2007
|
|
4800 | 4800 | 5200 | 08-01-2007
|
|
5200 | 5200 | 4800 | 08-08-2007
|
|
3500 | 4800 | 5200 | 08-15-2007
|
|
4200 | 5200 | 3500 | 12-10-2007
|
|
4200 | 3500 | 4500 | 01-01-2008
|
|
4200 | 4500 | 4200 | 01-01-2008
|
|
(10 rows)
|
|
|
|
select first_value(salary) over(order by enroll_date groups between 1 following and 3 following
|
|
exclude current row),
|
|
lead(salary) over(order by enroll_date groups between 1 following and 3 following exclude ties),
|
|
nth_value(salary, 1) over(order by enroll_date groups between 1 following and 3 following
|
|
exclude ties),
|
|
salary, enroll_date from empsalary;
|
|
first_value | lead | nth_value | salary | enroll_date
|
|
-------------+------+-----------+--------+-------------
|
|
3900 | 6000 | 3900 | 5000 | 10-01-2006
|
|
3900 | 3900 | 3900 | 6000 | 10-01-2006
|
|
4800 | 4800 | 4800 | 3900 | 12-23-2006
|
|
4800 | 5200 | 4800 | 4800 | 08-01-2007
|
|
4800 | 4800 | 4800 | 5200 | 08-01-2007
|
|
5200 | 5200 | 5200 | 4800 | 08-08-2007
|
|
3500 | 3500 | 3500 | 5200 | 08-15-2007
|
|
4500 | 4500 | 4500 | 3500 | 12-10-2007
|
|
| 4200 | | 4500 | 01-01-2008
|
|
| | | 4200 | 01-01-2008
|
|
(10 rows)
|
|
|
|
select last_value(salary) over(order by enroll_date groups between 1 following and 3 following
|
|
exclude group),
|
|
lag(salary) over(order by enroll_date groups between 1 following and 3 following exclude group),
|
|
salary, enroll_date from empsalary;
|
|
last_value | lag | salary | enroll_date
|
|
------------+------+--------+-------------
|
|
4800 | | 5000 | 10-01-2006
|
|
4800 | 5000 | 6000 | 10-01-2006
|
|
5200 | 6000 | 3900 | 12-23-2006
|
|
3500 | 3900 | 4800 | 08-01-2007
|
|
3500 | 4800 | 5200 | 08-01-2007
|
|
4200 | 5200 | 4800 | 08-08-2007
|
|
4200 | 4800 | 5200 | 08-15-2007
|
|
4200 | 5200 | 3500 | 12-10-2007
|
|
| 3500 | 4500 | 01-01-2008
|
|
| 4500 | 4200 | 01-01-2008
|
|
(10 rows)
|
|
|
|
-- Show differences in offset interpretation between ROWS, RANGE, and GROUPS
|
|
WITH cte (x) AS (
|
|
SELECT * FROM generate_series(1, 35, 2)
|
|
)
|
|
SELECT x, (sum(x) over w)
|
|
FROM cte
|
|
WINDOW w AS (ORDER BY x rows between 1 preceding and 1 following);
|
|
x | sum
|
|
----+-----
|
|
1 | 4
|
|
3 | 9
|
|
5 | 15
|
|
7 | 21
|
|
9 | 27
|
|
11 | 33
|
|
13 | 39
|
|
15 | 45
|
|
17 | 51
|
|
19 | 57
|
|
21 | 63
|
|
23 | 69
|
|
25 | 75
|
|
27 | 81
|
|
29 | 87
|
|
31 | 93
|
|
33 | 99
|
|
35 | 68
|
|
(18 rows)
|
|
|
|
WITH cte (x) AS (
|
|
SELECT * FROM generate_series(1, 35, 2)
|
|
)
|
|
SELECT x, (sum(x) over w)
|
|
FROM cte
|
|
WINDOW w AS (ORDER BY x range between 1 preceding and 1 following);
|
|
x | sum
|
|
----+-----
|
|
1 | 1
|
|
3 | 3
|
|
5 | 5
|
|
7 | 7
|
|
9 | 9
|
|
11 | 11
|
|
13 | 13
|
|
15 | 15
|
|
17 | 17
|
|
19 | 19
|
|
21 | 21
|
|
23 | 23
|
|
25 | 25
|
|
27 | 27
|
|
29 | 29
|
|
31 | 31
|
|
33 | 33
|
|
35 | 35
|
|
(18 rows)
|
|
|
|
WITH cte (x) AS (
|
|
SELECT * FROM generate_series(1, 35, 2)
|
|
)
|
|
SELECT x, (sum(x) over w)
|
|
FROM cte
|
|
WINDOW w AS (ORDER BY x groups between 1 preceding and 1 following);
|
|
x | sum
|
|
----+-----
|
|
1 | 4
|
|
3 | 9
|
|
5 | 15
|
|
7 | 21
|
|
9 | 27
|
|
11 | 33
|
|
13 | 39
|
|
15 | 45
|
|
17 | 51
|
|
19 | 57
|
|
21 | 63
|
|
23 | 69
|
|
25 | 75
|
|
27 | 81
|
|
29 | 87
|
|
31 | 93
|
|
33 | 99
|
|
35 | 68
|
|
(18 rows)
|
|
|
|
WITH cte (x) AS (
|
|
select 1 union all select 1 union all select 1 union all
|
|
SELECT * FROM generate_series(5, 49, 2)
|
|
)
|
|
SELECT x, (sum(x) over w)
|
|
FROM cte
|
|
WINDOW w AS (ORDER BY x rows between 1 preceding and 1 following);
|
|
x | sum
|
|
----+-----
|
|
1 | 2
|
|
1 | 3
|
|
1 | 7
|
|
5 | 13
|
|
7 | 21
|
|
9 | 27
|
|
11 | 33
|
|
13 | 39
|
|
15 | 45
|
|
17 | 51
|
|
19 | 57
|
|
21 | 63
|
|
23 | 69
|
|
25 | 75
|
|
27 | 81
|
|
29 | 87
|
|
31 | 93
|
|
33 | 99
|
|
35 | 105
|
|
37 | 111
|
|
39 | 117
|
|
41 | 123
|
|
43 | 129
|
|
45 | 135
|
|
47 | 141
|
|
49 | 96
|
|
(26 rows)
|
|
|
|
WITH cte (x) AS (
|
|
select 1 union all select 1 union all select 1 union all
|
|
SELECT * FROM generate_series(5, 49, 2)
|
|
)
|
|
SELECT x, (sum(x) over w)
|
|
FROM cte
|
|
WINDOW w AS (ORDER BY x range between 1 preceding and 1 following);
|
|
x | sum
|
|
----+-----
|
|
1 | 3
|
|
1 | 3
|
|
1 | 3
|
|
5 | 5
|
|
7 | 7
|
|
9 | 9
|
|
11 | 11
|
|
13 | 13
|
|
15 | 15
|
|
17 | 17
|
|
19 | 19
|
|
21 | 21
|
|
23 | 23
|
|
25 | 25
|
|
27 | 27
|
|
29 | 29
|
|
31 | 31
|
|
33 | 33
|
|
35 | 35
|
|
37 | 37
|
|
39 | 39
|
|
41 | 41
|
|
43 | 43
|
|
45 | 45
|
|
47 | 47
|
|
49 | 49
|
|
(26 rows)
|
|
|
|
WITH cte (x) AS (
|
|
select 1 union all select 1 union all select 1 union all
|
|
SELECT * FROM generate_series(5, 49, 2)
|
|
)
|
|
SELECT x, (sum(x) over w)
|
|
FROM cte
|
|
WINDOW w AS (ORDER BY x groups between 1 preceding and 1 following);
|
|
x | sum
|
|
----+-----
|
|
1 | 8
|
|
1 | 8
|
|
1 | 8
|
|
5 | 15
|
|
7 | 21
|
|
9 | 27
|
|
11 | 33
|
|
13 | 39
|
|
15 | 45
|
|
17 | 51
|
|
19 | 57
|
|
21 | 63
|
|
23 | 69
|
|
25 | 75
|
|
27 | 81
|
|
29 | 87
|
|
31 | 93
|
|
33 | 99
|
|
35 | 105
|
|
37 | 111
|
|
39 | 117
|
|
41 | 123
|
|
43 | 129
|
|
45 | 135
|
|
47 | 141
|
|
49 | 96
|
|
(26 rows)
|
|
|
|
-- with UNION
|
|
SELECT count(*) OVER (PARTITION BY four) FROM (SELECT * FROM tenk1 UNION ALL SELECT * FROM tenk2)s LIMIT 0;
|
|
count
|
|
-------
|
|
(0 rows)
|
|
|
|
-- check some degenerate cases
|
|
create temp table t1 (f1 int, f2 int8);
|
|
insert into t1 values (1,1),(1,2),(2,2);
|
|
select f1, sum(f1) over (partition by f1
|
|
range between 1 preceding and 1 following)
|
|
from t1 where f1 = f2; -- error, must have order by
|
|
ERROR: RANGE with offset PRECEDING/FOLLOWING requires exactly one ORDER BY column
|
|
LINE 1: select f1, sum(f1) over (partition by f1
|
|
^
|
|
explain (costs off)
|
|
select f1, sum(f1) over (partition by f1 order by f2
|
|
range between 1 preceding and 1 following)
|
|
from t1 where f1 = f2;
|
|
QUERY PLAN
|
|
---------------------------------
|
|
WindowAgg
|
|
-> Sort
|
|
Sort Key: f1
|
|
-> Seq Scan on t1
|
|
Filter: (f1 = f2)
|
|
(5 rows)
|
|
|
|
select f1, sum(f1) over (partition by f1 order by f2
|
|
range between 1 preceding and 1 following)
|
|
from t1 where f1 = f2;
|
|
f1 | sum
|
|
----+-----
|
|
1 | 1
|
|
2 | 2
|
|
(2 rows)
|
|
|
|
select f1, sum(f1) over (partition by f1, f1 order by f2
|
|
range between 2 preceding and 1 preceding)
|
|
from t1 where f1 = f2;
|
|
f1 | sum
|
|
----+-----
|
|
1 |
|
|
2 |
|
|
(2 rows)
|
|
|
|
select f1, sum(f1) over (partition by f1, f2 order by f2
|
|
range between 1 following and 2 following)
|
|
from t1 where f1 = f2;
|
|
f1 | sum
|
|
----+-----
|
|
1 |
|
|
2 |
|
|
(2 rows)
|
|
|
|
select f1, sum(f1) over (partition by f1
|
|
groups between 1 preceding and 1 following)
|
|
from t1 where f1 = f2; -- error, must have order by
|
|
ERROR: GROUPS mode requires an ORDER BY clause
|
|
LINE 1: select f1, sum(f1) over (partition by f1
|
|
^
|
|
explain (costs off)
|
|
select f1, sum(f1) over (partition by f1 order by f2
|
|
groups between 1 preceding and 1 following)
|
|
from t1 where f1 = f2;
|
|
QUERY PLAN
|
|
---------------------------------
|
|
WindowAgg
|
|
-> Sort
|
|
Sort Key: f1
|
|
-> Seq Scan on t1
|
|
Filter: (f1 = f2)
|
|
(5 rows)
|
|
|
|
select f1, sum(f1) over (partition by f1 order by f2
|
|
groups between 1 preceding and 1 following)
|
|
from t1 where f1 = f2;
|
|
f1 | sum
|
|
----+-----
|
|
1 | 1
|
|
2 | 2
|
|
(2 rows)
|
|
|
|
select f1, sum(f1) over (partition by f1, f1 order by f2
|
|
groups between 2 preceding and 1 preceding)
|
|
from t1 where f1 = f2;
|
|
f1 | sum
|
|
----+-----
|
|
1 |
|
|
2 |
|
|
(2 rows)
|
|
|
|
select f1, sum(f1) over (partition by f1, f2 order by f2
|
|
groups between 1 following and 2 following)
|
|
from t1 where f1 = f2;
|
|
f1 | sum
|
|
----+-----
|
|
1 |
|
|
2 |
|
|
(2 rows)
|
|
|
|
-- ordering by a non-integer constant is allowed
|
|
SELECT rank() OVER (ORDER BY length('abc'));
|
|
rank
|
|
------
|
|
1
|
|
(1 row)
|
|
|
|
-- can't order by another window function
|
|
SELECT rank() OVER (ORDER BY rank() OVER (ORDER BY random()));
|
|
ERROR: window functions are not allowed in window definitions
|
|
LINE 1: SELECT rank() OVER (ORDER BY rank() OVER (ORDER BY random())...
|
|
^
|
|
-- some other errors
|
|
SELECT * FROM empsalary WHERE row_number() OVER (ORDER BY salary) < 10;
|
|
ERROR: window functions are not allowed in WHERE
|
|
LINE 1: SELECT * FROM empsalary WHERE row_number() OVER (ORDER BY sa...
|
|
^
|
|
SELECT * FROM empsalary INNER JOIN tenk1 ON row_number() OVER (ORDER BY salary) < 10;
|
|
ERROR: window functions are not allowed in JOIN conditions
|
|
LINE 1: SELECT * FROM empsalary INNER JOIN tenk1 ON row_number() OVE...
|
|
^
|
|
SELECT rank() OVER (ORDER BY 1), count(*) FROM empsalary GROUP BY 1;
|
|
ERROR: window functions are not allowed in GROUP BY
|
|
LINE 1: SELECT rank() OVER (ORDER BY 1), count(*) FROM empsalary GRO...
|
|
^
|
|
SELECT * FROM rank() OVER (ORDER BY random());
|
|
ERROR: syntax error at or near "ORDER"
|
|
LINE 1: SELECT * FROM rank() OVER (ORDER BY random());
|
|
^
|
|
DELETE FROM empsalary WHERE (rank() OVER (ORDER BY random())) > 10;
|
|
ERROR: window functions are not allowed in WHERE
|
|
LINE 1: DELETE FROM empsalary WHERE (rank() OVER (ORDER BY random())...
|
|
^
|
|
DELETE FROM empsalary RETURNING rank() OVER (ORDER BY random());
|
|
ERROR: window functions are not allowed in RETURNING
|
|
LINE 1: DELETE FROM empsalary RETURNING rank() OVER (ORDER BY random...
|
|
^
|
|
SELECT count(*) OVER w FROM tenk1 WINDOW w AS (ORDER BY unique1), w AS (ORDER BY unique1);
|
|
ERROR: window "w" is already defined
|
|
LINE 1: ...w FROM tenk1 WINDOW w AS (ORDER BY unique1), w AS (ORDER BY ...
|
|
^
|
|
SELECT rank() OVER (PARTITION BY four, ORDER BY ten) FROM tenk1;
|
|
ERROR: syntax error at or near "ORDER"
|
|
LINE 1: SELECT rank() OVER (PARTITION BY four, ORDER BY ten) FROM te...
|
|
^
|
|
SELECT count() OVER () FROM tenk1;
|
|
ERROR: count(*) must be used to call a parameterless aggregate function
|
|
LINE 1: SELECT count() OVER () FROM tenk1;
|
|
^
|
|
SELECT generate_series(1, 100) OVER () FROM empsalary;
|
|
ERROR: OVER specified, but generate_series is not a window function nor an aggregate function
|
|
LINE 1: SELECT generate_series(1, 100) OVER () FROM empsalary;
|
|
^
|
|
SELECT ntile(0) OVER (ORDER BY ten), ten, four FROM tenk1;
|
|
ERROR: argument of ntile must be greater than zero
|
|
SELECT nth_value(four, 0) OVER (ORDER BY ten), ten, four FROM tenk1;
|
|
ERROR: argument of nth_value must be greater than zero
|
|
-- filter
|
|
SELECT sum(salary), row_number() OVER (ORDER BY depname), sum(
|
|
sum(salary) FILTER (WHERE enroll_date > '2007-01-01')
|
|
) FILTER (WHERE depname <> 'sales') OVER (ORDER BY depname DESC) AS "filtered_sum",
|
|
depname
|
|
FROM empsalary GROUP BY depname;
|
|
sum | row_number | filtered_sum | depname
|
|
-------+------------+--------------+-----------
|
|
25100 | 1 | 22600 | develop
|
|
7400 | 2 | 3500 | personnel
|
|
14600 | 3 | | sales
|
|
(3 rows)
|
|
|
|
-- Test pushdown of quals into a subquery containing window functions
|
|
-- pushdown is safe because all PARTITION BY clauses include depname:
|
|
EXPLAIN (COSTS OFF)
|
|
SELECT * FROM
|
|
(SELECT depname,
|
|
sum(salary) OVER (PARTITION BY depname) depsalary,
|
|
min(salary) OVER (PARTITION BY depname || 'A', depname) depminsalary
|
|
FROM empsalary) emp
|
|
WHERE depname = 'sales';
|
|
QUERY PLAN
|
|
--------------------------------------------------------------------------
|
|
Subquery Scan on emp
|
|
-> WindowAgg
|
|
-> WindowAgg
|
|
-> Sort
|
|
Sort Key: (((empsalary.depname)::text || 'A'::text))
|
|
-> Seq Scan on empsalary
|
|
Filter: ((depname)::text = 'sales'::text)
|
|
(7 rows)
|
|
|
|
-- pushdown is unsafe because there's a PARTITION BY clause without depname:
|
|
EXPLAIN (COSTS OFF)
|
|
SELECT * FROM
|
|
(SELECT depname,
|
|
sum(salary) OVER (PARTITION BY enroll_date) enroll_salary,
|
|
min(salary) OVER (PARTITION BY depname) depminsalary
|
|
FROM empsalary) emp
|
|
WHERE depname = 'sales';
|
|
QUERY PLAN
|
|
-------------------------------------------------------
|
|
Subquery Scan on emp
|
|
Filter: ((emp.depname)::text = 'sales'::text)
|
|
-> WindowAgg
|
|
-> Sort
|
|
Sort Key: empsalary.enroll_date
|
|
-> WindowAgg
|
|
-> Sort
|
|
Sort Key: empsalary.depname
|
|
-> Seq Scan on empsalary
|
|
(9 rows)
|
|
|
|
-- Test Sort node collapsing
|
|
EXPLAIN (COSTS OFF)
|
|
SELECT * FROM
|
|
(SELECT depname,
|
|
sum(salary) OVER (PARTITION BY depname order by empno) depsalary,
|
|
min(salary) OVER (PARTITION BY depname, empno order by enroll_date) depminsalary
|
|
FROM empsalary) emp
|
|
WHERE depname = 'sales';
|
|
QUERY PLAN
|
|
----------------------------------------------------------------------
|
|
Subquery Scan on emp
|
|
-> WindowAgg
|
|
-> WindowAgg
|
|
-> Sort
|
|
Sort Key: empsalary.empno, empsalary.enroll_date
|
|
-> Seq Scan on empsalary
|
|
Filter: ((depname)::text = 'sales'::text)
|
|
(7 rows)
|
|
|
|
-- Test Sort node reordering
|
|
EXPLAIN (COSTS OFF)
|
|
SELECT
|
|
lead(1) OVER (PARTITION BY depname ORDER BY salary, enroll_date),
|
|
lag(1) OVER (PARTITION BY depname ORDER BY salary,enroll_date,empno)
|
|
FROM empsalary;
|
|
QUERY PLAN
|
|
-------------------------------------------------------------
|
|
WindowAgg
|
|
-> WindowAgg
|
|
-> Sort
|
|
Sort Key: depname, salary, enroll_date, empno
|
|
-> Seq Scan on empsalary
|
|
(5 rows)
|
|
|
|
-- cleanup
|
|
DROP TABLE empsalary;
|
|
-- test user-defined window function with named args and default args
|
|
CREATE FUNCTION nth_value_def(val anyelement, n integer = 1) RETURNS anyelement
|
|
LANGUAGE internal WINDOW IMMUTABLE STRICT AS 'window_nth_value';
|
|
SELECT nth_value_def(n := 2, val := ten) OVER (PARTITION BY four), ten, four
|
|
FROM (SELECT * FROM tenk1 WHERE unique2 < 10 ORDER BY four, ten) s;
|
|
nth_value_def | ten | four
|
|
---------------+-----+------
|
|
0 | 0 | 0
|
|
0 | 0 | 0
|
|
0 | 4 | 0
|
|
1 | 1 | 1
|
|
1 | 1 | 1
|
|
1 | 7 | 1
|
|
1 | 9 | 1
|
|
| 0 | 2
|
|
3 | 1 | 3
|
|
3 | 3 | 3
|
|
(10 rows)
|
|
|
|
SELECT nth_value_def(ten) OVER (PARTITION BY four), ten, four
|
|
FROM (SELECT * FROM tenk1 WHERE unique2 < 10 ORDER BY four, ten) s;
|
|
nth_value_def | ten | four
|
|
---------------+-----+------
|
|
0 | 0 | 0
|
|
0 | 0 | 0
|
|
0 | 4 | 0
|
|
1 | 1 | 1
|
|
1 | 1 | 1
|
|
1 | 7 | 1
|
|
1 | 9 | 1
|
|
0 | 0 | 2
|
|
1 | 1 | 3
|
|
1 | 3 | 3
|
|
(10 rows)
|
|
|
|
--
|
|
-- Test the basic moving-aggregate machinery
|
|
--
|
|
-- create aggregates that record the series of transform calls (these are
|
|
-- intentionally not true inverses)
|
|
CREATE FUNCTION logging_sfunc_nonstrict(text, anyelement) RETURNS text AS
|
|
$$ SELECT COALESCE($1, '') || '*' || quote_nullable($2) $$
|
|
LANGUAGE SQL IMMUTABLE;
|
|
CREATE FUNCTION logging_msfunc_nonstrict(text, anyelement) RETURNS text AS
|
|
$$ SELECT COALESCE($1, '') || '+' || quote_nullable($2) $$
|
|
LANGUAGE SQL IMMUTABLE;
|
|
CREATE FUNCTION logging_minvfunc_nonstrict(text, anyelement) RETURNS text AS
|
|
$$ SELECT $1 || '-' || quote_nullable($2) $$
|
|
LANGUAGE SQL IMMUTABLE;
|
|
CREATE AGGREGATE logging_agg_nonstrict (anyelement)
|
|
(
|
|
stype = text,
|
|
sfunc = logging_sfunc_nonstrict,
|
|
mstype = text,
|
|
msfunc = logging_msfunc_nonstrict,
|
|
minvfunc = logging_minvfunc_nonstrict
|
|
);
|
|
CREATE AGGREGATE logging_agg_nonstrict_initcond (anyelement)
|
|
(
|
|
stype = text,
|
|
sfunc = logging_sfunc_nonstrict,
|
|
mstype = text,
|
|
msfunc = logging_msfunc_nonstrict,
|
|
minvfunc = logging_minvfunc_nonstrict,
|
|
initcond = 'I',
|
|
minitcond = 'MI'
|
|
);
|
|
CREATE FUNCTION logging_sfunc_strict(text, anyelement) RETURNS text AS
|
|
$$ SELECT $1 || '*' || quote_nullable($2) $$
|
|
LANGUAGE SQL STRICT IMMUTABLE;
|
|
CREATE FUNCTION logging_msfunc_strict(text, anyelement) RETURNS text AS
|
|
$$ SELECT $1 || '+' || quote_nullable($2) $$
|
|
LANGUAGE SQL STRICT IMMUTABLE;
|
|
CREATE FUNCTION logging_minvfunc_strict(text, anyelement) RETURNS text AS
|
|
$$ SELECT $1 || '-' || quote_nullable($2) $$
|
|
LANGUAGE SQL STRICT IMMUTABLE;
|
|
CREATE AGGREGATE logging_agg_strict (text)
|
|
(
|
|
stype = text,
|
|
sfunc = logging_sfunc_strict,
|
|
mstype = text,
|
|
msfunc = logging_msfunc_strict,
|
|
minvfunc = logging_minvfunc_strict
|
|
);
|
|
CREATE AGGREGATE logging_agg_strict_initcond (anyelement)
|
|
(
|
|
stype = text,
|
|
sfunc = logging_sfunc_strict,
|
|
mstype = text,
|
|
msfunc = logging_msfunc_strict,
|
|
minvfunc = logging_minvfunc_strict,
|
|
initcond = 'I',
|
|
minitcond = 'MI'
|
|
);
|
|
-- test strict and non-strict cases
|
|
SELECT
|
|
p::text || ',' || i::text || ':' || COALESCE(v::text, 'NULL') AS row,
|
|
logging_agg_nonstrict(v) over wnd as nstrict,
|
|
logging_agg_nonstrict_initcond(v) over wnd as nstrict_init,
|
|
logging_agg_strict(v::text) over wnd as strict,
|
|
logging_agg_strict_initcond(v) over wnd as strict_init
|
|
FROM (VALUES
|
|
(1, 1, NULL),
|
|
(1, 2, 'a'),
|
|
(1, 3, 'b'),
|
|
(1, 4, NULL),
|
|
(1, 5, NULL),
|
|
(1, 6, 'c'),
|
|
(2, 1, NULL),
|
|
(2, 2, 'x'),
|
|
(3, 1, 'z')
|
|
) AS t(p, i, v)
|
|
WINDOW wnd AS (PARTITION BY P ORDER BY i ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)
|
|
ORDER BY p, i;
|
|
row | nstrict | nstrict_init | strict | strict_init
|
|
----------+-----------------------------------------------+-------------------------------------------------+-----------+----------------
|
|
1,1:NULL | +NULL | MI+NULL | | MI
|
|
1,2:a | +NULL+'a' | MI+NULL+'a' | a | MI+'a'
|
|
1,3:b | +NULL+'a'-NULL+'b' | MI+NULL+'a'-NULL+'b' | a+'b' | MI+'a'+'b'
|
|
1,4:NULL | +NULL+'a'-NULL+'b'-'a'+NULL | MI+NULL+'a'-NULL+'b'-'a'+NULL | a+'b'-'a' | MI+'a'+'b'-'a'
|
|
1,5:NULL | +NULL+'a'-NULL+'b'-'a'+NULL-'b'+NULL | MI+NULL+'a'-NULL+'b'-'a'+NULL-'b'+NULL | | MI
|
|
1,6:c | +NULL+'a'-NULL+'b'-'a'+NULL-'b'+NULL-NULL+'c' | MI+NULL+'a'-NULL+'b'-'a'+NULL-'b'+NULL-NULL+'c' | c | MI+'c'
|
|
2,1:NULL | +NULL | MI+NULL | | MI
|
|
2,2:x | +NULL+'x' | MI+NULL+'x' | x | MI+'x'
|
|
3,1:z | +'z' | MI+'z' | z | MI+'z'
|
|
(9 rows)
|
|
|
|
-- and again, but with filter
|
|
SELECT
|
|
p::text || ',' || i::text || ':' ||
|
|
CASE WHEN f THEN COALESCE(v::text, 'NULL') ELSE '-' END as row,
|
|
logging_agg_nonstrict(v) filter(where f) over wnd as nstrict_filt,
|
|
logging_agg_nonstrict_initcond(v) filter(where f) over wnd as nstrict_init_filt,
|
|
logging_agg_strict(v::text) filter(where f) over wnd as strict_filt,
|
|
logging_agg_strict_initcond(v) filter(where f) over wnd as strict_init_filt
|
|
FROM (VALUES
|
|
(1, 1, true, NULL),
|
|
(1, 2, false, 'a'),
|
|
(1, 3, true, 'b'),
|
|
(1, 4, false, NULL),
|
|
(1, 5, false, NULL),
|
|
(1, 6, false, 'c'),
|
|
(2, 1, false, NULL),
|
|
(2, 2, true, 'x'),
|
|
(3, 1, true, 'z')
|
|
) AS t(p, i, f, v)
|
|
WINDOW wnd AS (PARTITION BY p ORDER BY i ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)
|
|
ORDER BY p, i;
|
|
row | nstrict_filt | nstrict_init_filt | strict_filt | strict_init_filt
|
|
----------+--------------+-------------------+-------------+------------------
|
|
1,1:NULL | +NULL | MI+NULL | | MI
|
|
1,2:- | +NULL | MI+NULL | | MI
|
|
1,3:b | +'b' | MI+'b' | b | MI+'b'
|
|
1,4:- | +'b' | MI+'b' | b | MI+'b'
|
|
1,5:- | | MI | | MI
|
|
1,6:- | | MI | | MI
|
|
2,1:- | | MI | | MI
|
|
2,2:x | +'x' | MI+'x' | x | MI+'x'
|
|
3,1:z | +'z' | MI+'z' | z | MI+'z'
|
|
(9 rows)
|
|
|
|
-- test that volatile arguments disable moving-aggregate mode
|
|
SELECT
|
|
i::text || ':' || COALESCE(v::text, 'NULL') as row,
|
|
logging_agg_strict(v::text)
|
|
over wnd as inverse,
|
|
logging_agg_strict(v::text || CASE WHEN random() < 0 then '?' ELSE '' END)
|
|
over wnd as noinverse
|
|
FROM (VALUES
|
|
(1, 'a'),
|
|
(2, 'b'),
|
|
(3, 'c')
|
|
) AS t(i, v)
|
|
WINDOW wnd AS (ORDER BY i ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)
|
|
ORDER BY i;
|
|
row | inverse | noinverse
|
|
-----+---------------+-----------
|
|
1:a | a | a
|
|
2:b | a+'b' | a*'b'
|
|
3:c | a+'b'-'a'+'c' | b*'c'
|
|
(3 rows)
|
|
|
|
SELECT
|
|
i::text || ':' || COALESCE(v::text, 'NULL') as row,
|
|
logging_agg_strict(v::text) filter(where true)
|
|
over wnd as inverse,
|
|
logging_agg_strict(v::text) filter(where random() >= 0)
|
|
over wnd as noinverse
|
|
FROM (VALUES
|
|
(1, 'a'),
|
|
(2, 'b'),
|
|
(3, 'c')
|
|
) AS t(i, v)
|
|
WINDOW wnd AS (ORDER BY i ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)
|
|
ORDER BY i;
|
|
row | inverse | noinverse
|
|
-----+---------------+-----------
|
|
1:a | a | a
|
|
2:b | a+'b' | a*'b'
|
|
3:c | a+'b'-'a'+'c' | b*'c'
|
|
(3 rows)
|
|
|
|
-- test that non-overlapping windows don't use inverse transitions
|
|
SELECT
|
|
logging_agg_strict(v::text) OVER wnd
|
|
FROM (VALUES
|
|
(1, 'a'),
|
|
(2, 'b'),
|
|
(3, 'c')
|
|
) AS t(i, v)
|
|
WINDOW wnd AS (ORDER BY i ROWS BETWEEN CURRENT ROW AND CURRENT ROW)
|
|
ORDER BY i;
|
|
logging_agg_strict
|
|
--------------------
|
|
a
|
|
b
|
|
c
|
|
(3 rows)
|
|
|
|
-- test that returning NULL from the inverse transition functions
|
|
-- restarts the aggregation from scratch. The second aggregate is supposed
|
|
-- to test cases where only some aggregates restart, the third one checks
|
|
-- that one aggregate restarting doesn't cause others to restart.
|
|
CREATE FUNCTION sum_int_randrestart_minvfunc(int4, int4) RETURNS int4 AS
|
|
$$ SELECT CASE WHEN random() < 0.2 THEN NULL ELSE $1 - $2 END $$
|
|
LANGUAGE SQL STRICT;
|
|
CREATE AGGREGATE sum_int_randomrestart (int4)
|
|
(
|
|
stype = int4,
|
|
sfunc = int4pl,
|
|
mstype = int4,
|
|
msfunc = int4pl,
|
|
minvfunc = sum_int_randrestart_minvfunc
|
|
);
|
|
WITH
|
|
vs AS (
|
|
SELECT i, (random() * 100)::int4 AS v
|
|
FROM generate_series(1, 100) AS i
|
|
),
|
|
sum_following AS (
|
|
SELECT i, SUM(v) OVER
|
|
(ORDER BY i DESC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS s
|
|
FROM vs
|
|
)
|
|
SELECT DISTINCT
|
|
sum_following.s = sum_int_randomrestart(v) OVER fwd AS eq1,
|
|
-sum_following.s = sum_int_randomrestart(-v) OVER fwd AS eq2,
|
|
100*3+(vs.i-1)*3 = length(logging_agg_nonstrict(''::text) OVER fwd) AS eq3
|
|
FROM vs
|
|
JOIN sum_following ON sum_following.i = vs.i
|
|
WINDOW fwd AS (
|
|
ORDER BY vs.i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
|
|
);
|
|
eq1 | eq2 | eq3
|
|
-----+-----+-----
|
|
t | t | t
|
|
(1 row)
|
|
|
|
--
|
|
-- Test various built-in aggregates that have moving-aggregate support
|
|
--
|
|
-- test inverse transition functions handle NULLs properly
|
|
SELECT i,AVG(v::bigint) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,1),(2,2),(3,NULL),(4,NULL)) t(i,v);
|
|
i | avg
|
|
---+--------------------
|
|
1 | 1.5000000000000000
|
|
2 | 2.0000000000000000
|
|
3 |
|
|
4 |
|
|
(4 rows)
|
|
|
|
SELECT i,AVG(v::int) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,1),(2,2),(3,NULL),(4,NULL)) t(i,v);
|
|
i | avg
|
|
---+--------------------
|
|
1 | 1.5000000000000000
|
|
2 | 2.0000000000000000
|
|
3 |
|
|
4 |
|
|
(4 rows)
|
|
|
|
SELECT i,AVG(v::smallint) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,1),(2,2),(3,NULL),(4,NULL)) t(i,v);
|
|
i | avg
|
|
---+--------------------
|
|
1 | 1.5000000000000000
|
|
2 | 2.0000000000000000
|
|
3 |
|
|
4 |
|
|
(4 rows)
|
|
|
|
SELECT i,AVG(v::numeric) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,1.5),(2,2.5),(3,NULL),(4,NULL)) t(i,v);
|
|
i | avg
|
|
---+--------------------
|
|
1 | 2.0000000000000000
|
|
2 | 2.5000000000000000
|
|
3 |
|
|
4 |
|
|
(4 rows)
|
|
|
|
SELECT i,AVG(v::interval) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,'1 sec'),(2,'2 sec'),(3,NULL),(4,NULL)) t(i,v);
|
|
i | avg
|
|
---+------------
|
|
1 | @ 1.5 secs
|
|
2 | @ 2 secs
|
|
3 |
|
|
4 |
|
|
(4 rows)
|
|
|
|
SELECT i,SUM(v::smallint) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,1),(2,2),(3,NULL),(4,NULL)) t(i,v);
|
|
i | sum
|
|
---+-----
|
|
1 | 3
|
|
2 | 2
|
|
3 |
|
|
4 |
|
|
(4 rows)
|
|
|
|
SELECT i,SUM(v::int) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,1),(2,2),(3,NULL),(4,NULL)) t(i,v);
|
|
i | sum
|
|
---+-----
|
|
1 | 3
|
|
2 | 2
|
|
3 |
|
|
4 |
|
|
(4 rows)
|
|
|
|
SELECT i,SUM(v::bigint) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,1),(2,2),(3,NULL),(4,NULL)) t(i,v);
|
|
i | sum
|
|
---+-----
|
|
1 | 3
|
|
2 | 2
|
|
3 |
|
|
4 |
|
|
(4 rows)
|
|
|
|
SELECT i,SUM(v::money) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,'1.10'),(2,'2.20'),(3,NULL),(4,NULL)) t(i,v);
|
|
i | sum
|
|
---+-------
|
|
1 | $3.30
|
|
2 | $2.20
|
|
3 |
|
|
4 |
|
|
(4 rows)
|
|
|
|
SELECT i,SUM(v::interval) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,'1 sec'),(2,'2 sec'),(3,NULL),(4,NULL)) t(i,v);
|
|
i | sum
|
|
---+----------
|
|
1 | @ 3 secs
|
|
2 | @ 2 secs
|
|
3 |
|
|
4 |
|
|
(4 rows)
|
|
|
|
SELECT i,SUM(v::numeric) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,1.1),(2,2.2),(3,NULL),(4,NULL)) t(i,v);
|
|
i | sum
|
|
---+-----
|
|
1 | 3.3
|
|
2 | 2.2
|
|
3 |
|
|
4 |
|
|
(4 rows)
|
|
|
|
SELECT SUM(n::numeric) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,1.01),(2,2),(3,3)) v(i,n);
|
|
sum
|
|
------
|
|
6.01
|
|
5
|
|
3
|
|
(3 rows)
|
|
|
|
SELECT i,COUNT(v) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,1),(2,2),(3,NULL),(4,NULL)) t(i,v);
|
|
i | count
|
|
---+-------
|
|
1 | 2
|
|
2 | 1
|
|
3 | 0
|
|
4 | 0
|
|
(4 rows)
|
|
|
|
SELECT i,COUNT(*) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,1),(2,2),(3,NULL),(4,NULL)) t(i,v);
|
|
i | count
|
|
---+-------
|
|
1 | 4
|
|
2 | 3
|
|
3 | 2
|
|
4 | 1
|
|
(4 rows)
|
|
|
|
SELECT VAR_POP(n::bigint) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,600),(2,470),(3,170),(4,430),(5,300)) r(i,n);
|
|
var_pop
|
|
-----------------------
|
|
21704.000000000000
|
|
13868.750000000000
|
|
11266.666666666667
|
|
4225.0000000000000000
|
|
0
|
|
(5 rows)
|
|
|
|
SELECT VAR_POP(n::int) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,600),(2,470),(3,170),(4,430),(5,300)) r(i,n);
|
|
var_pop
|
|
-----------------------
|
|
21704.000000000000
|
|
13868.750000000000
|
|
11266.666666666667
|
|
4225.0000000000000000
|
|
0
|
|
(5 rows)
|
|
|
|
SELECT VAR_POP(n::smallint) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,600),(2,470),(3,170),(4,430),(5,300)) r(i,n);
|
|
var_pop
|
|
-----------------------
|
|
21704.000000000000
|
|
13868.750000000000
|
|
11266.666666666667
|
|
4225.0000000000000000
|
|
0
|
|
(5 rows)
|
|
|
|
SELECT VAR_POP(n::numeric) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,600),(2,470),(3,170),(4,430),(5,300)) r(i,n);
|
|
var_pop
|
|
-----------------------
|
|
21704.000000000000
|
|
13868.750000000000
|
|
11266.666666666667
|
|
4225.0000000000000000
|
|
0
|
|
(5 rows)
|
|
|
|
SELECT VAR_SAMP(n::bigint) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,600),(2,470),(3,170),(4,430),(5,300)) r(i,n);
|
|
var_samp
|
|
-----------------------
|
|
27130.000000000000
|
|
18491.666666666667
|
|
16900.000000000000
|
|
8450.0000000000000000
|
|
|
|
(5 rows)
|
|
|
|
SELECT VAR_SAMP(n::int) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,600),(2,470),(3,170),(4,430),(5,300)) r(i,n);
|
|
var_samp
|
|
-----------------------
|
|
27130.000000000000
|
|
18491.666666666667
|
|
16900.000000000000
|
|
8450.0000000000000000
|
|
|
|
(5 rows)
|
|
|
|
SELECT VAR_SAMP(n::smallint) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,600),(2,470),(3,170),(4,430),(5,300)) r(i,n);
|
|
var_samp
|
|
-----------------------
|
|
27130.000000000000
|
|
18491.666666666667
|
|
16900.000000000000
|
|
8450.0000000000000000
|
|
|
|
(5 rows)
|
|
|
|
SELECT VAR_SAMP(n::numeric) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,600),(2,470),(3,170),(4,430),(5,300)) r(i,n);
|
|
var_samp
|
|
-----------------------
|
|
27130.000000000000
|
|
18491.666666666667
|
|
16900.000000000000
|
|
8450.0000000000000000
|
|
|
|
(5 rows)
|
|
|
|
SELECT VARIANCE(n::bigint) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,600),(2,470),(3,170),(4,430),(5,300)) r(i,n);
|
|
variance
|
|
-----------------------
|
|
27130.000000000000
|
|
18491.666666666667
|
|
16900.000000000000
|
|
8450.0000000000000000
|
|
|
|
(5 rows)
|
|
|
|
SELECT VARIANCE(n::int) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,600),(2,470),(3,170),(4,430),(5,300)) r(i,n);
|
|
variance
|
|
-----------------------
|
|
27130.000000000000
|
|
18491.666666666667
|
|
16900.000000000000
|
|
8450.0000000000000000
|
|
|
|
(5 rows)
|
|
|
|
SELECT VARIANCE(n::smallint) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,600),(2,470),(3,170),(4,430),(5,300)) r(i,n);
|
|
variance
|
|
-----------------------
|
|
27130.000000000000
|
|
18491.666666666667
|
|
16900.000000000000
|
|
8450.0000000000000000
|
|
|
|
(5 rows)
|
|
|
|
SELECT VARIANCE(n::numeric) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,600),(2,470),(3,170),(4,430),(5,300)) r(i,n);
|
|
variance
|
|
-----------------------
|
|
27130.000000000000
|
|
18491.666666666667
|
|
16900.000000000000
|
|
8450.0000000000000000
|
|
|
|
(5 rows)
|
|
|
|
SELECT STDDEV_POP(n::bigint) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,NULL),(2,600),(3,470),(4,170),(5,430),(6,300)) r(i,n);
|
|
stddev_pop
|
|
---------------------
|
|
147.322774885623
|
|
147.322774885623
|
|
117.765657133139
|
|
106.144555520604
|
|
65.0000000000000000
|
|
0
|
|
(6 rows)
|
|
|
|
SELECT STDDEV_POP(n::int) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,NULL),(2,600),(3,470),(4,170),(5,430),(6,300)) r(i,n);
|
|
stddev_pop
|
|
---------------------
|
|
147.322774885623
|
|
147.322774885623
|
|
117.765657133139
|
|
106.144555520604
|
|
65.0000000000000000
|
|
0
|
|
(6 rows)
|
|
|
|
SELECT STDDEV_POP(n::smallint) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,NULL),(2,600),(3,470),(4,170),(5,430),(6,300)) r(i,n);
|
|
stddev_pop
|
|
---------------------
|
|
147.322774885623
|
|
147.322774885623
|
|
117.765657133139
|
|
106.144555520604
|
|
65.0000000000000000
|
|
0
|
|
(6 rows)
|
|
|
|
SELECT STDDEV_POP(n::numeric) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,NULL),(2,600),(3,470),(4,170),(5,430),(6,300)) r(i,n);
|
|
stddev_pop
|
|
---------------------
|
|
147.322774885623
|
|
147.322774885623
|
|
117.765657133139
|
|
106.144555520604
|
|
65.0000000000000000
|
|
0
|
|
(6 rows)
|
|
|
|
SELECT STDDEV_SAMP(n::bigint) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,NULL),(2,600),(3,470),(4,170),(5,430),(6,300)) r(i,n);
|
|
stddev_samp
|
|
---------------------
|
|
164.711869639076
|
|
164.711869639076
|
|
135.984067694222
|
|
130.000000000000
|
|
91.9238815542511782
|
|
|
|
(6 rows)
|
|
|
|
SELECT STDDEV_SAMP(n::int) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,NULL),(2,600),(3,470),(4,170),(5,430),(6,300)) r(i,n);
|
|
stddev_samp
|
|
---------------------
|
|
164.711869639076
|
|
164.711869639076
|
|
135.984067694222
|
|
130.000000000000
|
|
91.9238815542511782
|
|
|
|
(6 rows)
|
|
|
|
SELECT STDDEV_SAMP(n::smallint) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,NULL),(2,600),(3,470),(4,170),(5,430),(6,300)) r(i,n);
|
|
stddev_samp
|
|
---------------------
|
|
164.711869639076
|
|
164.711869639076
|
|
135.984067694222
|
|
130.000000000000
|
|
91.9238815542511782
|
|
|
|
(6 rows)
|
|
|
|
SELECT STDDEV_SAMP(n::numeric) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(1,NULL),(2,600),(3,470),(4,170),(5,430),(6,300)) r(i,n);
|
|
stddev_samp
|
|
---------------------
|
|
164.711869639076
|
|
164.711869639076
|
|
135.984067694222
|
|
130.000000000000
|
|
91.9238815542511782
|
|
|
|
(6 rows)
|
|
|
|
SELECT STDDEV(n::bigint) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(0,NULL),(1,600),(2,470),(3,170),(4,430),(5,300)) r(i,n);
|
|
stddev
|
|
---------------------
|
|
164.711869639076
|
|
164.711869639076
|
|
135.984067694222
|
|
130.000000000000
|
|
91.9238815542511782
|
|
|
|
(6 rows)
|
|
|
|
SELECT STDDEV(n::int) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(0,NULL),(1,600),(2,470),(3,170),(4,430),(5,300)) r(i,n);
|
|
stddev
|
|
---------------------
|
|
164.711869639076
|
|
164.711869639076
|
|
135.984067694222
|
|
130.000000000000
|
|
91.9238815542511782
|
|
|
|
(6 rows)
|
|
|
|
SELECT STDDEV(n::smallint) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(0,NULL),(1,600),(2,470),(3,170),(4,430),(5,300)) r(i,n);
|
|
stddev
|
|
---------------------
|
|
164.711869639076
|
|
164.711869639076
|
|
135.984067694222
|
|
130.000000000000
|
|
91.9238815542511782
|
|
|
|
(6 rows)
|
|
|
|
SELECT STDDEV(n::numeric) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
|
FROM (VALUES(0,NULL),(1,600),(2,470),(3,170),(4,430),(5,300)) r(i,n);
|
|
stddev
|
|
---------------------
|
|
164.711869639076
|
|
164.711869639076
|
|
135.984067694222
|
|
130.000000000000
|
|
91.9238815542511782
|
|
|
|
(6 rows)
|
|
|
|
-- test that inverse transition functions work with various frame options
|
|
SELECT i,SUM(v::int) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND CURRENT ROW)
|
|
FROM (VALUES(1,1),(2,2),(3,NULL),(4,NULL)) t(i,v);
|
|
i | sum
|
|
---+-----
|
|
1 | 1
|
|
2 | 2
|
|
3 |
|
|
4 |
|
|
(4 rows)
|
|
|
|
SELECT i,SUM(v::int) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING)
|
|
FROM (VALUES(1,1),(2,2),(3,NULL),(4,NULL)) t(i,v);
|
|
i | sum
|
|
---+-----
|
|
1 | 3
|
|
2 | 2
|
|
3 |
|
|
4 |
|
|
(4 rows)
|
|
|
|
SELECT i,SUM(v::int) OVER (ORDER BY i ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)
|
|
FROM (VALUES(1,1),(2,2),(3,3),(4,4)) t(i,v);
|
|
i | sum
|
|
---+-----
|
|
1 | 3
|
|
2 | 6
|
|
3 | 9
|
|
4 | 7
|
|
(4 rows)
|
|
|
|
-- ensure aggregate over numeric properly recovers from NaN values
|
|
SELECT a, b,
|
|
SUM(b) OVER(ORDER BY A ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)
|
|
FROM (VALUES(1,1::numeric),(2,2),(3,'NaN'),(4,3),(5,4)) t(a,b);
|
|
a | b | sum
|
|
---+-----+-----
|
|
1 | 1 | 1
|
|
2 | 2 | 3
|
|
3 | NaN | NaN
|
|
4 | 3 | NaN
|
|
5 | 4 | 7
|
|
(5 rows)
|
|
|
|
-- It might be tempting for someone to add an inverse trans function for
|
|
-- float and double precision. This should not be done as it can give incorrect
|
|
-- results. This test should fail if anyone ever does this without thinking too
|
|
-- hard about it.
|
|
SELECT to_char(SUM(n::float8) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING),'999999999999999999999D9')
|
|
FROM (VALUES(1,1e20),(2,1)) n(i,n);
|
|
to_char
|
|
--------------------------
|
|
100000000000000000000
|
|
1.0
|
|
(2 rows)
|
|
|
|
SELECT i, b, bool_and(b) OVER w, bool_or(b) OVER w
|
|
FROM (VALUES (1,true), (2,true), (3,false), (4,false), (5,true)) v(i,b)
|
|
WINDOW w AS (ORDER BY i ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING);
|
|
i | b | bool_and | bool_or
|
|
---+---+----------+---------
|
|
1 | t | t | t
|
|
2 | t | f | t
|
|
3 | f | f | f
|
|
4 | f | f | t
|
|
5 | t | t | t
|
|
(5 rows)
|
|
|