首先,我想指出我已经尝试了几乎所有的方法。在过去的8个小时里,我一直在尝试让我的列表有序,并且我已经应用了这里找到的数十种解决方案。
这里是带有示例数据的SQL Fiddle。我发现一个页面可以按正确顺序对我的列表进行排序。
这里是带有示例数据的SQL Fiddle。我发现一个页面可以按正确顺序对我的列表进行排序。
1
2
2.B3
5
9
10 A-1
10 A-3
10 B-4
10 B-5
11
12
B3-43
B3-44
B3 - 48
B3 - 49
Basztowa 3
Basztowa 4
Basztowa 5
Basztowa 7
Basztowa 9
D.1
D.2
D.10
D.11
D.12
Kabaty ul. Pod lipą 4
但是我无法使用MySQL复现这个问题。
如果可能的话,我想避免使用PHP来解决我的问题,因为据我所知,DBMS已经针对此类操作进行了优化。如有任何帮助,我将不胜感激。
@更新
感谢@Jakumi,我创建了两个函数来帮助我解决问题。
你需要创建一个列以存储排序友好格式的值(zeropadded_name),在更新和插入时创建触发器,以使zeropadded_name填充name更改时,就可以按zeropadded_name排序并享受它!
辅助函数
regex_replace
- 它的任务是通过删除所有非字母数字字符来帮助我们清理值。lpad_numbers
- 填充字符串中的每个数字。它有点丑陋,因为我不太了解MySQL函数,但嘿,它很有效,而且速度很快。
例子:
SELECT lpad_numbers(regex_replace('[^a-zA-Z0-9]', ' ', 'B3 - A-5'));
#B0003A0005
DROP FUNCTION IF EXISTS regex_replace;
CREATE FUNCTION `regex_replace`(
pattern VARCHAR(1000)
CHARSET utf8
COLLATE utf8_polish_ci,
replacement VARCHAR(1000)
CHARSET utf8
COLLATE utf8_polish_ci,
original VARCHAR(1000)
CHARSET utf8
COLLATE utf8_polish_ci
) RETURNS varchar(1000) CHARSET utf8
DETERMINISTIC
BEGIN
DECLARE temp VARCHAR(1000)
CHARSET utf8
COLLATE utf8_polish_ci;
DECLARE ch VARCHAR(1)
CHARSET utf8
COLLATE utf8_polish_ci;
DECLARE i INT;
SET i = 1;
SET temp = '';
IF original REGEXP pattern
THEN
loop_label: LOOP
IF i > CHAR_LENGTH(original)
THEN
LEAVE loop_label;
END IF;
SET ch = SUBSTRING(original, i, 1);
IF NOT ch REGEXP pattern
THEN
SET temp = CONCAT(temp, ch);
ELSE
SET temp = CONCAT(temp, replacement);
END IF;
SET i = i + 1;
END LOOP;
ELSE
SET temp = original;
END IF;
RETURN temp;
END;
DROP FUNCTION IF EXISTS lpad_numbers;
CREATE FUNCTION `lpad_numbers`(str VARCHAR(256)) RETURNS varchar(256) CHARSET utf8 COLLATE utf8_polish_ci
BEGIN
DECLARE i, len SMALLINT DEFAULT 1;
DECLARE ret VARCHAR(256) DEFAULT '';
DECLARE num VARCHAR(256) DEFAULT '';
DECLARE c CHAR(1);
IF str IS NULL
THEN
RETURN "";
END IF;
SET len = CHAR_LENGTH(str);
REPEAT
BEGIN
SET c = MID(str, i, 1);
IF c BETWEEN '0' AND '9'
THEN
SET num = c;
SET i = i + 1;
REPEAT
BEGIN
SET c = MID(str, i, 1);
SET num = CONCAT(num, c);
SET i = i + 1;
END;
UNTIL c NOT BETWEEN '0' AND '9' END REPEAT;
SET ret = CONCAT(ret, LPAD(num, 4, '0'));
ELSE
SET ret = CONCAT(ret, c);
SET i = i + 1;
END IF;
END;
UNTIL i > len END REPEAT;
RETURN ret;
END;