Re: Ordering of window functions with no order specified?

From: Andreas Kretschmer <andreas(at)a-kretschmer(dot)de>
To: pgsql-general(at)postgresql(dot)org
Subject: Re: Ordering of window functions with no order specified?
Date: 2017-06-15 05:26:57
Message-ID: cc8431b9-7805-9e34-ad8b-4dced9d422eb@a-kretschmer.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

Am 15.06.2017 um 06:34 schrieb Ken Tanzer:
> Hi. If you use a window function and don't specify an order, will the
> rows be processed in the same order as the query results?
>
> In this particular case, I'm wondering about row_number(), and whether
> I explicitly need to repeat the ordering that's already specified in
> the query?
>
> SELECT a,b,c,row_number()
> OVER (PARTITION BY a) -- Do I need an ORDER BY c,b here?
> FROM foo
> ORDER BY c,b
>
> Also, I'm interested in both what if any behavior is guaranteed, and
> what gets done in practice. (i.e., a SELECT with no order doesn't
> have guarantees, but in practice seems to return the results in the
> order they were added to the table. Is it something similar here?)
>

That's different queries and results:

test=# create table foo as select s%5 a, random() as b, random() as c
from generate_series(1, 20) s;
SELECT 20

test=*# select a, b, c, row_number() over (partition by a) from foo
order by c,b;
a | b | c | row_number
---+--------------------+---------------------+------------
3 | 0.293813084252179 | 0.00748801836743951 | 4
2 | 0.366433540824801 | 0.0825160844251513 | 3
2 | 0.646373085677624 | 0.144253523554653 | 2
1 | 0.436142998747528 | 0.149559560697526 | 4
4 | 0.766950330231339 | 0.279563031159341 | 2
4 | 0.780563669744879 | 0.36753943329677 | 4
4 | 0.521357014775276 | 0.37830171873793 | 1
3 | 0.641054477542639 | 0.438840930350125 | 3
0 | 0.23528463486582 | 0.506252389866859 | 1
1 | 0.883372921962291 | 0.607358017936349 | 2
2 | 0.0624627070501447 | 0.610814236104488 | 4
1 | 0.203920441213995 | 0.680096843745559 | 3
0 | 0.945639119483531 | 0.686336697079241 | 3
2 | 0.360363553743809 | 0.702507333364338 | 1
0 | 0.493005351629108 | 0.739280233159661 | 4
0 | 0.844849191140383 | 0.756641649641097 | 2
1 | 0.375874035060406 | 0.771526555530727 | 1
4 | 0.0844886344857514 | 0.837361172772944 | 3
3 | 0.50597962597385 | 0.841444775927812 | 2
3 | 0.0100470245815814 | 0.899044481106102 | 1
(20 Zeilen)

test=*# select a, b, c, row_number() over (partition by a order by c,b)
from foo order by c,b;
a | b | c | row_number
---+--------------------+---------------------+------------
3 | 0.293813084252179 | 0.00748801836743951 | 1
2 | 0.366433540824801 | 0.0825160844251513 | 1
2 | 0.646373085677624 | 0.144253523554653 | 2
1 | 0.436142998747528 | 0.149559560697526 | 1
4 | 0.766950330231339 | 0.279563031159341 | 1
4 | 0.780563669744879 | 0.36753943329677 | 2
4 | 0.521357014775276 | 0.37830171873793 | 3
3 | 0.641054477542639 | 0.438840930350125 | 2
0 | 0.23528463486582 | 0.506252389866859 | 1
1 | 0.883372921962291 | 0.607358017936349 | 2
2 | 0.0624627070501447 | 0.610814236104488 | 3
1 | 0.203920441213995 | 0.680096843745559 | 3
0 | 0.945639119483531 | 0.686336697079241 | 2
2 | 0.360363553743809 | 0.702507333364338 | 4
0 | 0.493005351629108 | 0.739280233159661 | 3
0 | 0.844849191140383 | 0.756641649641097 | 4
1 | 0.375874035060406 | 0.771526555530727 | 4
4 | 0.0844886344857514 | 0.837361172772944 | 4
3 | 0.50597962597385 | 0.841444775927812 | 3
3 | 0.0100470245815814 | 0.899044481106102 | 4
(20 Zeilen)

And also different execution plans:

test=*# explain analyse select a, b, c, row_number() over (partition by
a) from foo order by c,b;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------
Sort (cost=239.18..243.43 rows=1700 width=20) (actual
time=0.134..0.138 rows=20 loops=1)
Sort Key: c, b
Sort Method: quicksort Memory: 26kB
-> WindowAgg (cost=118.22..147.97 rows=1700 width=20) (actual
time=0.056..0.101 rows=20 loops=1)
-> Sort (cost=118.22..122.47 rows=1700 width=20) (actual
time=0.048..0.054 rows=20 loops=1)
Sort Key: a
Sort Method: quicksort Memory: 26kB
-> Seq Scan on foo (cost=0.00..27.00 rows=1700
width=20) (actual time=0.021..0.028 rows=20 loops=1)
Planning time: 0.104 ms
Execution time: 0.200 ms
(10 Zeilen)

test=*# explain analyse select a, b, c, row_number() over (partition by
a order by c,b) from foo order by c,b;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------
Sort (cost=247.68..251.93 rows=1700 width=20) (actual
time=0.115..0.119 rows=20 loops=1)
Sort Key: c, b
Sort Method: quicksort Memory: 26kB
-> WindowAgg (cost=118.22..156.47 rows=1700 width=20) (actual
time=0.056..0.090 rows=20 loops=1)
-> Sort (cost=118.22..122.47 rows=1700 width=20) (actual
time=0.048..0.054 rows=20 loops=1)
Sort Key: a, c, b
Sort Method: quicksort Memory: 26kB
-> Seq Scan on foo (cost=0.00..27.00 rows=1700
width=20) (actual time=0.019..0.025 rows=20 loops=1)
Planning time: 0.100 ms
Execution time: 0.173 ms
(10 Zeilen)

As you can see, different sort keys for the WindowAgg-Sort.

Please don't mix the ORDER BY for the window-function and for the
result-set. Use alwyas an explicit ORDER BY if you expect an ordered result.

Regards, Andreas

--
2ndQuadrant - The PostgreSQL Support Company.
www.2ndQuadrant.com

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message David G. Johnston 2017-06-15 05:27:19 Re: Ordering of window functions with no order specified?
Previous Message Ken Tanzer 2017-06-15 04:34:33 Ordering of window functions with no order specified?