Ordinals bind to the SELECT list's shape, not to meaning — write-once convenience that becomes a landmine the first time anyone edits the columns (the insert_select_position family, ORDER-BY-flavored). The DISTINCT case is the same logical-order lesson HAVING and QUALIFY taught: ORDER BY runs on the output, and DISTINCT's output no longer carries unselected columns.
SELECT bpm, song FROM setlist ORDER BY 2 DESC;
SELECT bpm, song FROM setlist ORDER BY bpm DESC;
After a column was reordered, ORDER BY 2 sorted by the song name, not the bpm — an ordinal binds to the SELECT list's position, so editing the columns silently changes what you sort by; naming the column is stable.
Named columns/aliases in ORDER BY; ordinals only in throwaway console work.