Sorting by Fixed-Length Substrings
6.13.1 Problem
You want to sort using parts of a column that occur at a given position within the column.
6.13.2 Solution
Pull out the parts you need with LEFT( ), MID( ), or RIGHT( ) and sort them.
6.13.3 Discussion
Suppose you have a housewares table that acts as a catalog for houseware furnishings, and that items are identified by 11-character ID values consisting of three subparts: a three-character category abbreviation (such as DIN for "dining room" or KIT for "kitchen"), a five-digit serial number, and a two-character country code indicating where the part is manufactured:
mysql> SELECT * FROM housewares; +------------+------------------+ | id | description | +------------+------------------+ | DIN40672US | dining table | | KIT00372UK | garbage disposal | | KIT01729JP | microwave oven | | BED00038SG | bedside lamp | | BTH00485US | shower stall | | BTH00415JP | lavatory | +------------+------------------+
This is not necessarily a good way to store complex ID values, and later we'll consider how to represent them using separate columns (Recipe 11.14). But for now, assume that the values must be stored as just shown.
If you want to sort records from this table based on the id values, you'd just use the entire column value:
mysql> SELECT * FROM housewares ORDER BY id; +------------+------------------+ | id | description | +------------+------------------+ | BED00038SG | bedside lamp | | BTH00415JP | lavatory | | BTH00485US | shower stall | | DIN40672US | dining table | | KIT00372UK | garbage disposal | | KIT01729JP | microwave oven | +------------+------------------+
But you might also have a need to sort on any of the three subparts (for example, to sort by country of manufacture). For that kind of operation, it's helpful to use functions that pull out pieces of a column, such as LEFT( ), MID( ), and RIGHT( ). These functions can be used to break apart the id values into their three components:
mysql> SELECT id, -> LEFT(id,3) AS category, -> MID(id,4,5) AS serial, -> RIGHT(id,2) AS country -> FROM housewares; +------------+----------+--------+---------+ | id | category | serial | country | +------------+----------+--------+---------+ | DIN40672US | DIN | 40672 | US | | KIT00372UK | KIT | 00372 | UK | | KIT01729JP | KIT | 01729 | JP | | BED00038SG | BED | 00038 | SG | | BTH00485US | BTH | 00485 | US | | BTH00415JP | BTH | 00415 | JP | +------------+----------+--------+---------+
Any of those fixed-length substrings of the id values can be used for sorting, either alone or in combination. To sort by product category, extract the category value and use it in the ORDER BY clause:
mysql> SELECT * FROM housewares ORDER BY LEFT(id,3); +------------+------------------+ | id | description | +------------+------------------+ | BED00038SG | bedside lamp | | BTH00485US | shower stall | | BTH00415JP | lavatory | | DIN40672US | dining table | | KIT00372UK | garbage disposal | | KIT01729JP | microwave oven | +------------+------------------+
To sort rows by product serial number, use MID( ) to extract the middle five characters from the id values, beginning with the fourth:
mysql> SELECT * FROM housewares ORDER BY MID(id,4,5); +------------+------------------+ | id | description | +------------+------------------+ | BED00038SG | bedside lamp | | KIT00372UK | garbage disposal | | BTH00415JP | lavatory | | BTH00485US | shower stall | | KIT01729JP | microwave oven | | DIN40672US | dining table | +------------+------------------+
This appears to be a numeric sort, but it's actually a string sort, because MID( ) returns strings. It just so happens that the lexical and numeric sort order are the same in this case due to the fact that the "numbers" have leading zeros to make them all the same length.
To sort by country code, use the rightmost two characters of the id values:
mysql> SELECT * FROM housewares ORDER BY RIGHT(id,2); +------------+------------------+ | id | description | +------------+------------------+ | KIT01729JP | microwave oven | | BTH00415JP | lavatory | | BED00038SG | bedside lamp | | KIT00372UK | garbage disposal | | DIN40672US | dining table | | BTH00485US | shower stall | +------------+------------------+
You can also sort using combinations of substrings. For example, to sort by country code and serial number, the query looks like this:
mysql> SELECT * FROM housewares ORDER BY RIGHT(id,2), MID(id,4,5);
+------------+------------------+
| id | description |
+------------+------------------+
| BTH00415JP | lavatory |
| KIT01729JP | microwave oven |
| BED00038SG | bedside lamp |
| KIT00372UK | garbage disposal |
| BTH00485US | shower stall |
| DIN40672US | dining table |
+------------+------------------+
Категории