29  Which rows do you want?

Which rows does the question actually need? Half of daily work is narrowing. The recipes here are the narrowings that recur: the top few, the top one per group, the ones above a bar, the ones without a twin. The owning chapters are Keeping rows and Sorting and taking.

29.1 The top few

run('
  sales
    then sort [revenue] descending
    then take 5
')
date region product quantity revenue cost
2026-01-26 West Gadget 5 300 200
2026-05-06 North Gadget 4 240 160
2026-03-03 East Doohickey 5 200 125
2026-01-09 East Widget 8 200 80
2025-12-22 North Widget 6 150 60
sales |> sort(descending(revenue)) |> take(5)
date region product quantity revenue cost
2026-01-26 West Gadget 5 300 200
2026-05-06 North Gadget 4 240 160
2026-03-03 East Doohickey 5 200 125
2026-01-09 East Widget 8 200 80
2025-12-22 North Widget 6 150 60
sales >> sort(descending(col.revenue)) >> take(5)
date region product quantity revenue cost
2026-01-26 West Gadget 5 300 200
2026-05-06 North Gadget 4 240 160
2026-03-03 East Doohickey 5 200 125
2026-01-09 East Widget 8 200 80
2025-12-22 North Widget 6 150 60

sales then sort [revenue] descending then take 5

One verb away. The bottom few: take_last(5), with the sort left as it is. Dropping descending instead reaches the same rows in the opposite order, which is a different table. The top few of a different measure: change the sort key, and nothing else. The top five scores rather than five rows: take(5, ties = TRUE), which keeps every row level with the fifth.

29.2 The top one per group

run('
  sales
    then sort [revenue] descending
    then take 1 by [region]
')
date region product quantity revenue cost
2026-01-26 West Gadget 5 300 200
2026-05-06 North Gadget 4 240 160
2026-01-09 East Widget 8 200 80
sales |> sort(descending(revenue)) |> take(1, by = region)
date region product quantity revenue cost
2026-01-26 West Gadget 5 300 200
2026-05-06 North Gadget 4 240 160
2026-01-09 East Widget 8 200 80
sales >> sort(descending(col.revenue)) >> take(1, by = col.region)
date region product quantity revenue cost
2026-01-26 West Gadget 5 300 200
2026-05-06 North Gadget 4 240 160
2026-01-09 East Widget 8 200 80

sales then sort [revenue] descending then take 1 by [region]

One verb away. The top two: take(2, by = region). The most recent per group instead of the largest: sort by date instead of revenue, which has its own section in sorting and taking.

29.3 The rows above a bar

run('
  sales
    then keep where ([quantity] >= 5)
    then sort [quantity] descending
')
date region product quantity revenue cost
2026-06-19 East Sprocket 10 150 120
2026-01-09 East Widget 8 200 80
2025-12-22 North Widget 6 150 60
2026-07-08 West Sprocket 6 90 72
2026-01-26 West Gadget 5 300 200
2026-03-03 East Doohickey 5 200 125
2026-10-02 West Widget 5 125 50
sales |> keep(quantity >= 5) |> sort(descending(quantity))
date region product quantity revenue cost
2026-06-19 East Sprocket 10 150 120
2026-01-09 East Widget 8 200 80
2025-12-22 North Widget 6 150 60
2026-07-08 West Sprocket 6 90 72
2026-01-26 West Gadget 5 300 200
2026-03-03 East Doohickey 5 200 125
2026-10-02 West Widget 5 125 50
sales >> keep(col.quantity >= 5) >> sort(descending(col.quantity))
date region product quantity revenue cost
2026-06-19 East Sprocket 10 150 120
2026-01-09 East Widget 8 200 80
2025-12-22 North Widget 6 150 60
2026-07-08 West Sprocket 6 90 72
2026-01-26 West Gadget 5 300 200
2026-03-03 East Doohickey 5 200 125
2026-10-02 West Widget 5 125 50

sales then keep where [quantity] >= 5 then sort [quantity] descending

One verb away. A bar on a derived number: add the number first, then keep on it. A bar per group (“orders above their region’s average”) is the same two steps with by on the add: add(avg = average(revenue), by = region), then keep the rows above it. The words that repeat teaches that use of by.

29.4 The rows without a twin

run('
  sales
    then pick [region, product]
    then drop_duplicates
')
region product
East Doohickey
East Gadget
East Sprocket
East Widget
North Doohickey
North Gadget
North Widget
West Doohickey
West Gadget
West Sprocket
West Widget
sales |> pick(region, product) |> drop_duplicates()
region product
East Doohickey
East Gadget
East Sprocket
East Widget
North Doohickey
North Gadget
North Widget
West Doohickey
West Gadget
West Sprocket
West Widget
sales >> pick(col.region, col.product) >> drop_duplicates()
region product
East Doohickey
East Gadget
East Sprocket
East Widget
North Doohickey
North Gadget
North Widget
West Doohickey
West Gadget
West Sprocket
West Widget

sales then pick [region, product] then drop_duplicates

Every region-product pairing that occurred, once each. Narrow first, then drop: the columns you pick are the definition of what counts as a twin. The owning chapter is Renaming and repeats. The pairings that never occurred are the opposite question, which the rows that are not there answers.

One verb away. Whole rows, one per group, is a different question with a forced honesty in it: sort then take 1 by, saying which row you mean.

29.5 What this section refuses

“Some rows” is not a question, and the grammar declines to pretend it is. The first of each group, with nothing said about order:

sales |> take(1, by = product) |> collect()
Error:
! 
illegal: `take ... by` gives the first rows of each group, and nothing has said what order the rows are in, so there is no first. Sort before it: `then sort [when] descending then take 1 by [id]`
  |
2 |   then take 1 by [product]
  |        ^^^^^^^^^^^^^^^^^^
try:
    collect(sales >> take(1, by = col.product))
except GodError as refusal:
    print(refusal)

illegal: `take ... by` gives the first rows of each group, and nothing has said what order the rows are in, so there is no first. Sort before it: `then sort [when] descending then take 1 by [id]`
  |
2 |   then take 1 by [product]
  |        ^^^^^^^^^^^^^^^^^^

The repair is one sort, and the refusal names it. Every recipe on this page that took a first or a top said its order aloud. Saying the order is what makes a sentence mean the same thing on every run, on every engine, this year and next. One pick is still the engine’s: a cut that falls inside a tie. with ties, from sorting and taking, keeps the whole tie, so nothing is left to pick.