The biggest problem was in the modeling decision, which prioritized the storage of the formatted value, and not the semantic value.
Preferred solution: to remodel
The ideal solution would be to convert the column to some format that had the padding of the preserved boxes, whether string or preferably numeric if the maximum value with padding "fits" in the digits of the chosen type.
Instead of
1.15
1.2.17.01
would store, for example:
01015000000
01002017001
I used the AABBBCCCDDD format (two houses in the first level, and 3 in the following), but this should be adjusted according to your application.
The points would be placed only in the screen display, and removed in the input, with its validation and formatting.
Intermediate solution
A possible solution is the creation of a Function in Mysql string in groups, multiplying their factors by a constant corresponding to the possible levels, effectively ordering.
Another is using substrings, but this involves extracting each group, adding zeros before and cutting to a fixed measure:
SELECT
conta
FROM
planodecontas
ORDER BY
0 + SUBSTRING_INDEX( CONCAT( conta, '.0.0.0' ), '.', 1 ),
0 + SUBSTRING_INDEX( SUBSTRING_INDEX( CONCAT( conta, '.0.0.0' ), '.', 2 ), '.', -1),
0 + SUBSTRING_INDEX( SUBSTRING_INDEX( CONCAT( conta, '.0.0.0' ), '.', 3 ), '.', -1),
0 + SUBSTRING_INDEX( SUBSTRING_INDEX( CONCAT( conta, '.0.0.0' ), '.', 4 ), '.', -1)
The problem in both cases is that they become "ugly and expensive" functions for use in ordination. Doing in the client-application (sort after recover, with the main language of the code), may end up being better.
Solution "oriented to gambiarra":
Actually, it has a function that is made to interpret IPV4 numbers, which are strings with format AAA.BBB.CCC.DDD
, which is the INET_ATON
SELECT
conta
FROM
planodecontas
ORDER BY
INET_ATON( SUBSTRING_INDEX( CONCAT( conta, '.0.0.0' ), '.', 4 ) );
The limitation is that the INET_ATON
needs fixed number of groups for a balanced comparison, and only works with values from 0 to 255 per group.
To align the groups, we use
SUBSTRING_INDEX( CONCAT( conta, '.0.0.0' ), '.', 4 )
That takes 4 separate groups with .
of string concatenated.
I don’t recommend it, but it’s good you know it exists.
To tell you the truth, the biggest problem is misstoring the values. If they have this intended numerical sense, they should store as
10502001
instead of1.5.2.01
, and format on the screen, always remembering to leave the number of digits per drive reserved in a reasonable way. This is very common in systems with chart of accounts, documentation trees, versioning systems etc.– Bacco
Hello ! Exactly, my need is to be done numerical ordering, but I ended up posting all listing because it is very large, the highest values have up to 3 sublevels after the first point, can have up to 3 characters each level.
– Luís Felipe Dal Molin
The dot should be used only on the screen, and not on DB. Normally no formatting is stored in the database. If you need to format, do it in the client language of the system (I imagine you are using one). For example, a CNPJ is usually just a field with digits, no dots and dashes. A plan of accounts only a string of numbers prefixed by zero (usually 2 houses on level 2 and 3 houses or more). Even, this prevents that by mistake there is 1.02 and 1.2 in the base, which would give a bad mess. An ABBCCCDDDEEE format usually resolves.
– Bacco
I edited and put an example, please confirm that is according to the desired. Thank you !
– Luís Felipe Dal Molin