Shape / rows · All operations

Keep the rows with the largest or smallest values

A variant of Take the first or last rows

Sort by one or more columns and keep the N rows with the largest or smallest values.

Status

In arcform

Runs as a SQL step

arcform carries it as a sql: step today.

The DuckDB step

Keep the N rows with the largest or smallest values, sorting on two columns

It reads the orders table the proofs share. Create it first:

SQL
CREATE TABLE orders AS SELECT * FROM (VALUES
  (1,  'Alice Ng',      'north', DATE '2026-01-03', 120.00, 'widget', 'a|b',   '{"channel":"web","items":[1,2]}'),
  (2,  'alice ng',      'north', DATE '2026-01-05',  80.50, 'gadget', 'b',     '{"channel":"shop","items":[3]}'),
  (3,  'Bob  Okafor',   'south', DATE '2026-01-05', 300.00, 'widget', 'a|c',   '{"channel":"web","items":[4,5,6]}'),
  (4,  'Carla Díaz',    'east',  DATE '2026-01-09',  NULL,  'gizmo',  NULL,    '{"channel":"web","items":[]}'),
  (5,  'Bob Okafor',    'south', DATE '2026-01-12',  45.25, 'gadget', 'c',     '{"channel":"phone","items":[7]}'),
  (6,  'Dev Patel',     'west',  DATE '2026-01-12', 510.00, 'widget', 'a',     '{"channel":"web","items":[8,9]}'),
  (7,  'Carla Diaz',    'east',  DATE '2026-01-20',  99.99, 'gizmo',  'b|c',   '{"channel":"shop","items":[10]}'),
  (8,  'Dev Patel',     'west',  DATE '2026-02-02', 510.00, 'widget', 'a',     '{"channel":"web","items":[8,9]}'),
  (9,  'Eve Larsen',    NULL,    DATE '2026-02-03',  15.00, 'gadget', NULL,    '{"channel":"web","items":[11]}'),
  (10, 'Alice Ng',      'north', DATE '2026-02-10', 220.00, 'gizmo',  'a|b|c', '{"channel":"phone","items":[12,13]}')
) t(order_id, customer, region, order_date, amount, product, tags, meta);

Then run the statement:

SQL
-- largest three amounts; the two 510.00 orders tie, so the later order date comes first
CREATE TEMP TABLE largest AS
SELECT order_id, amount, order_date FROM orders ORDER BY amount DESC NULLS LAST, order_date DESC LIMIT 3;
-- smallest two amounts, leaving out the order with no amount
CREATE TEMP TABLE smallest AS
SELECT order_id, amount FROM orders WHERE amount IS NOT NULL ORDER BY amount ASC LIMIT 2;
-- the single largest: the tie at 510.00 goes to the later order date
CREATE TEMP TABLE winner AS
SELECT order_id FROM orders ORDER BY amount DESC NULLS LAST, order_date DESC LIMIT 1;
SELECT * FROM largest;
SELECT * FROM smallest;
SELECT CASE WHEN ((SELECT list(order_id ORDER BY amount DESC, order_date DESC) FROM largest) = [8, 6, 3] AND (SELECT order_id FROM winner) = 8 AND (SELECT list(order_id ORDER BY amount) FROM smallest) = [9, 5]) THEN 'as expected' ELSE error('the largest three were not orders 8, 6 and 3 with 8 first, or the smallest two were not orders 9 and 5') END AS verdict;
  • It needs nothing installed beyond DuckDB itself.
  • The statement checks its own result and raises an error when it is wrong: “the largest three were not orders 8, 6 and 3 with 8 first, or the smallest two were not orders 9 and 5”.
  • It passed on DuckDB v2.0.0 (Cyanoptera) d54cbbe3df.

What other tools call it

Meridian's classification; an independent blind rating agreed on 95.7% of 324 rows (variant, version 3).

EasyMorph (1)
  • Keep min/maxread 2026-09-27

    Keep or remove the rows holding the N largest or smallest values of a column

KNIME Analytics Platform (1)
  • Top k Row Filterread 2026-09-27

    Keep the top k rows under a user-defined sort order

Polars (2)
  • DataFrame.bottom_kread 2026-09-27

    Keep the k rows with the smallest values of the given columns

  • DataFrame.top_kread 2026-09-27

    Keep the k rows with the largest values of the given columns

Power Query M (4)
  • Table.Maxread 2026-09-27

    Return the row with the largest value under the comparison criteria, or a default

  • Table.MaxNread 2026-09-27

    Keep the N largest rows under the comparison criteria, or rows while a condition holds

  • Table.Minread 2026-09-27

    Return the row with the smallest value under the comparison criteria, or a default

  • Table.MinNread 2026-09-27

    Keep the N smallest rows under the comparison criteria, or rows while a condition holds

Talend (1)
  • tTopread 2026-09-27

    Sort rows and keep a given number of first rows

Background

Partial sorting returns the k smallest or k largest elements of a list in order; computing a Top 100 is a common practical example.[1] In pandas, nlargest returns the first n rows with the largest values in the given columns, in descending order.[2] In DuckDB, an ORDER BY followed by LIMIT 5 selects the top 5 rows, such as the five cities with the highest population.[3]

When to use it

In PostgreSQL, null values sort as if larger than any non-null value, so NULLS FIRST is the default for DESC order.[4] Write NULLS LAST explicitly on a descending sort for a top N, rather than relying on an engine's default. (Meridian's view)

In SQLite, the order in which two rows whose ORDER BY expressions all evaluate to equal values are returned is undefined.[5] In DuckDB, ORDER BY may not use a stable sorting algorithm.[6] In PostgreSQL, FETCH FIRST with the WITH TIES option returns any additional rows that tie for last place according to the ORDER BY, which is mandatory with that option.[7] In pandas, nlargest settles ties with keep: first prioritises the first occurrences, last the last, and all keeps every tie even if that selects more than n rows.[2] Decide what happens at the Nth place before you run it: add a sort column that breaks ties, or keep the ties on purpose, so the cut-off follows a rule. (Meridian's view)

In Polars, the output of top_k is not guaranteed to be in any particular order, so sort() is called afterwards if sorted output is wanted.[8]

The method

In PostgreSQL, when more than one sort expression is given, the later values are used to sort rows that are equal according to the earlier ones.[4] In PostgreSQL, the sort direction is set independently for each column, so ORDER BY x, y DESC is not the same as ORDER BY x DESC, y DESC.[4]

A partial heapsort inserts the first k elements into a heap and makes one pass over the rest, taking O(n log k) time, which is practical for small values of k.[1] Finding the k smallest elements without ordering them is equivalent to partition-based selection, and sorting those k afterwards costs O(n + k log k) operations in total.[1]

Compared with the alternatives

In pandas, nlargest is equivalent to sorting the values in descending order and taking the first n rows, but more performant.[2]