Numerical labels are very handy for relating data in a table catalogue to a map, especially when the amount of data is too large for a simple eyeball scan (more than 10 to 15 labels). Imagine having some 50 sites stored alphabetically in a catalogue: how do you find the site n° 32 on the map? The simplest approach is to order site labels on the map in some meaningful manner, typically in ascending order from north to south.

To obtain this we can use the Query builder which can talk SQL (sort of).

1) Create fields for x and y coordinates using Field calculator ($x returns the x coordinate and $y the other one).

2) Open the query builder under Layer Properties > General, and enter an expression with ORDER BY clause. We need to make a mock query before that, so if you do not want any exclusions enter a condition that all elements would satisfy (e.g. ID >= 0 or x_coordinate > 0 etc …).

Attention: textual criteria are denoted by single quotes ( ‘ ) .

For ordering north to south we need to use the field containing the y coordinate, and that in a reverse order (for typical coordinate systems of the northern hemisphere, at least): this is what the DESC clause means (descending order). If there are points with same y coordinates, we can add ordering on x axis, as below. Test and click Apply, when finished.

3) Now return to the field calculator and add a new field for ordered labels. The expression to return the row number is … $rownum or @row_number for QGIS 3. And voila!


I had some problems, namely when assigning the row number to a “virtual field” or to the label expression (?) It would certainly be cleaner to use virtual fields… Also, be sure to click all options for refreshing the query builder output (Test Query, Apply etc.).


Usually the x or y coordinate are precise enough to be unique, which means that the ordering will be only on the first specified axis. This may produce unpleasing results, forcing the reader to scan the map in horizontal lines. We can experiment with relaxing the coordinates to, say, 10 kilometres precision (on the first axis!) to relax the criteria and use the second axis as well [e.g. round(y, 10000)]

PS. There is also a sorting function integrated in the table view (upon a right click on a column name), but it just didn’t work for me (?) .