Doc: simplify the tutorial's window-function examples.
authorTom Lane <[email protected]>
Tue, 21 Jan 2025 19:43:21 +0000 (14:43 -0500)
committerTom Lane <[email protected]>
Tue, 21 Jan 2025 19:43:21 +0000 (14:43 -0500)
For the purposes of this discussion, row_number() is just as good
as rank(), and its behavior is easier to understand and describe.
So let's switch the examples to using row_number().

Along the way to checking the results given in the tutorial,
I found it helpful to extract the empsalary table we use in the
regression tests, which is evidently the same data that was used
to make these results.  So I shoved that into advanced.source
to improve the coverage of that file a little.  (There's still
several pages of the tutorial that are not included in it,
but at least now 3.5 Window Functions is covered.)

Suggested-by: "David G. Johnston" <[email protected]>
Author: Tom Lane <[email protected]>
Discussion: https://postgr.es/m/173737973383.1070.1832752929070067441@wrigleys.postgresql.org

doc/src/sgml/advanced.sgml
src/tutorial/advanced.source

index 755c9f148508425cc01155b13db33caac05fea03..e15a3323dfbfdd34803dc5715c043979cc50eb8f 100644 (file)
@@ -389,30 +389,32 @@ SELECT depname, empno, salary, avg(salary) OVER (PARTITION BY depname) FROM emps
 
 <programlisting>
 SELECT depname, empno, salary,
-       rank() OVER (PARTITION BY depname ORDER BY salary DESC)
+       row_number() OVER (PARTITION BY depname ORDER BY salary DESC)
 FROM empsalary;
 </programlisting>
 
 <screen>
-  depname  | empno | salary | rank
------------+-------+--------+------
- develop   |     8 |   6000 |    1
- develop   |    10 |   5200 |    2
- develop   |    11 |   5200 |    2
- develop   |     9 |   4500 |    4
- develop   |     7 |   4200 |    5
- personnel |     2 |   3900 |    1
- personnel |     5 |   3500 |    2
- sales     |     1 |   5000 |    1
- sales     |     4 |   4800 |    2
- sales     |     3 |   4800 |    2
+  depname  | empno | salary | row_number
+-----------+-------+--------+------------
+ develop   |     8 |   6000 |          1
+ develop   |    10 |   5200 |          2
+ develop   |    11 |   5200 |          3
+ develop   |     9 |   4500 |          4
+ develop   |     7 |   4200 |          5
+ personnel |     2 |   3900 |          1
+ personnel |     5 |   3500 |          2
+ sales     |     1 |   5000 |          1
+ sales     |     4 |   4800 |          2
+ sales     |     3 |   4800 |          3
 (10 rows)
 </screen>
 
-    As shown here, the <function>rank</function> function produces a numerical rank
-    for each distinct <literal>ORDER BY</literal> value in the current row's
-    partition, using the order defined by the <literal>ORDER BY</literal> clause.
-    <function>rank</function> needs no explicit parameter, because its behavior
+    As shown here, the <function>row_number</function> window function
+    assigns sequential numbers to the rows within each partition,
+    in the order defined by the <literal>ORDER BY</literal> clause
+    (with tied rows numbered in an unspecified order).
+    <function>row_number</function> needs no explicit parameter,
+    because its behavior
     is entirely determined by the <literal>OVER</literal> clause.
    </para>
 
@@ -527,14 +529,15 @@ SELECT salary, sum(salary) OVER (ORDER BY salary) FROM empsalary;
 SELECT depname, empno, salary, enroll_date
 FROM
   (SELECT depname, empno, salary, enroll_date,
-          rank() OVER (PARTITION BY depname ORDER BY salary DESC, empno) AS pos
+     row_number() OVER (PARTITION BY depname ORDER BY salary DESC, empno) AS pos
      FROM empsalary
   ) AS ss
 WHERE pos &lt; 3;
 </programlisting>
 
     The above query only shows the rows from the inner query having
-    <literal>rank</literal> less than 3.
+    <literal>row_number</literal> less than 3 (that is, the first
+    two rows for each department).
    </para>
 
    <para>
index 0c68b3344c359c38cd71cd6017ac359e9fe1bf6a..f46fced1a5f32b1be889f1c38bca6ba9680d0d54 100644 (file)
 --
 ---------------------------------------------------------------------------
 
+-----------------------------
+-- Window Functions
+-----------------------------
+
+-- a sample table
+CREATE TABLE empsalary (
+    depname text,
+    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, avg(salary) OVER (PARTITION BY depname)
+  FROM empsalary;
+
+SELECT depname, empno, salary,
+       row_number() OVER (PARTITION BY depname ORDER BY salary DESC)
+FROM empsalary;
+
+SELECT salary, sum(salary) OVER () FROM empsalary;
+
+SELECT salary, sum(salary) OVER (ORDER BY salary) FROM empsalary;
+
+SELECT depname, empno, salary, enroll_date
+FROM
+  (SELECT depname, empno, salary, enroll_date,
+     row_number() OVER (PARTITION BY depname ORDER BY salary DESC, empno) AS pos
+     FROM empsalary
+  ) AS ss
+WHERE pos < 3;
+
+SELECT sum(salary) OVER w, avg(salary) OVER w
+  FROM empsalary
+  WINDOW w AS (PARTITION BY depname ORDER BY salary DESC);
+
+DROP TABLE empsalary;
+
 -----------------------------
 -- Inheritance:
 -- A table can inherit from zero or more tables.  A query can reference