I\'ve ran into something I\'m not really sure how to handle here. I\'m building a database to store information on sports cards, and I\'m having a bit of an issue with some
MariaDB 10 and MySQL 8 support REGEXP_REPLACE. Using that, you can define a custom function:
DROP FUNCTION IF EXISTS zerofill_numbers;
CREATE FUNCTION zerofill_numbers(str TEXT, len TINYINT)
RETURNS text
NO SQL
DETERMINISTIC
RETURN REGEXP_REPLACE(
REGEXP_REPLACE(str, '(\\d+)', LPAD('\\1', len+2, 0)),
REPLACE('0*(\\d{$len})', '$len', len),
'\\1'
);
Now given the following test data:
DROP TABLE IF EXISTS `strings`;
CREATE TABLE IF NOT EXISTS `strings` (`str` text);
INSERT INTO `strings` (`str`) VALUES
('Bowman 52'),
('Bowman 54'),
('Bowman 147'),
('Bowman Chrome Prospects BCP32'),
('Bowman Chrome Prospects BCP61'),
('Bowman Chrome Prospects BCP97'),
('Bowman Chrome Prospects BCP125'),
('Topps 1'),
('Topps 3'),
('Topps 2a'),
('Topps 2b'),
('v9.9.3'),
('v9.10.3'),
('v11.3.4'),
('v9.9.11'),
('v11.3'),
('0.9'),
('0.11'),
('s09'),
('s11'),
('s0'),
('v9.0.1');
We can sort it with:
SELECT s.str
FROM strings s
ORDER BY zerofill_numbers(s.str, 10)
Here is the result:
0.9
0.11
Bowman 52
Bowman 54
Bowman 147
Bowman Chrome Prospects BCP32
Bowman Chrome Prospects BCP61
Bowman Chrome Prospects BCP97
Bowman Chrome Prospects BCP125
s0
s09
s11
Topps 1
Topps 2a
Topps 2b
Topps 3
v9.0.1
v9.9.3
v9.9.11
v9.10.3
v11.3
v11.3.4
The function will fill any number in in the string with zeros until it has the defined length.
Note 1: This will not sort decimal numbers correctly (see 0.9 and 0.11). You should also not try to use it for signed numbers.
Note 2: This function is based on the following answer: https://stackoverflow.com/a/46099386/5563083 - So if you find this answer helpfull, go and upvote the source.
Note 3: If you don't want to define a custom function, you can use the same method inline:
SELECT *
FROM strings
ORDER BY
REGEXP_REPLACE(REGEXP_REPLACE(str, '(\\d+)', LPAD('\\1', 10+2, 0)), '0*(\\d{10})', '\\1')