我的价值观如下:
1.1.2
9.1
2.2
4
1.2.3.4
3.2.14
3.2.1.4.2
.....
我需要使用mysql对这些值进行排序。这个数据类型是varbinary(300)。
所需的输出如下:
1.1.2
1.2.3.4
2.2
3.2.1.4.2
3.2.14
4
9.1
查询是:
select version_number from table order by version_number asc
它没有给出正确的排序顺序。
所需的输出是:
1.1.2
1.2.3.4
2.2
3.2.1.4.2
3.2.14
4
9.1
版本号最多为20位(如1.2.3.4.5.6.7.8.9.2.34)以及更多。没有特定的最大尺寸,标准版本就像上面提到的那样。
答案 0 :(得分:36)
尝试滥用INET_ATON
函数进行排序,如下所示:
SELECT version_number FROM table ORDER BY INET_ATON(SUBSTRING_INDEX(CONCAT(version_number,'.0.0.0'),'.',4))
这个技巧最初发布在mysql mailing list上,非常感谢原版海报Michael Stassen!
以下是他要说的话:
如果每个部分不大于255,您可以利用INET_ATON()来完成 你想要什么(直到第4部分)。诀窍是制作这些中的每一个 通过使用CONCAT添加'0.0.0'来确保每一个看起来像IP 行至少有4个部分,然后SUBSTRING_INDEX就拉出来了 前4个部分。
现在,我必须指出,因为我们正在对一个函数进行排序 列,而不是列本身,我们不能使用索引 列有助于排序。换句话说,排序将是 相对缓慢。
在后一种情况下,他推荐的解决方案类似于@spanky发布的解决方案(单独的列)。
答案 1 :(得分:5)
我会将它存储在三个单独的列中,每个列对应一个版本号。
使每列成为TINYINT,甚至在3列中创建索引。这应该简单。
然后你可以这样做:
select CONCAT(v1,'.',v2,'.',v3) AS version_number FROM table ORDER BY v1 asc, v2 asc, v3 asc
答案 2 :(得分:0)
如果您希望支持1.1-beta
等版本或使用不带INTE_ATON
的旧版MySql,可以通过拆分版本并将每个部分排序为整数和字符串来获得相同的排序: / p>
SELECT
version,
REPLACE(SUBSTRING(SUBSTRING_INDEX(version, '.', 1), LENGTH(SUBSTRING_INDEX(version, '.', 1 - 1)) + 1), '.', '') v1,
REPLACE(SUBSTRING(SUBSTRING_INDEX(version, '.', 2), LENGTH(SUBSTRING_INDEX(version, '.', 2 - 1)) + 1), '.', '') v2,
REPLACE(SUBSTRING(SUBSTRING_INDEX(version, '.', 3), LENGTH(SUBSTRING_INDEX(version, '.', 3 - 1)) + 1), '.', '') v3,
REPLACE(SUBSTRING(SUBSTRING_INDEX(version, '.', 4), LENGTH(SUBSTRING_INDEX(version, '.', 4 - 1)) + 1), '.', '') v4
FROM
versions_table
ORDER BY
0+v1, v1 DESC, 0+v2, v2 DESC, 0+v3, v3 DESC, 0+v4, v4 DESC;
答案 3 :(得分:0)
使用正则表达式。首先对值进行归一化:
SELECT REGEXP_REPLACE(
REGEXP_REPLACE(
REGEXP_REPLACE('v1.22.333', '^v', ''),
'(^|\\.)(\\d+)',
'\\100000\\2'
),
'0+(\\d{5})(\\.|$)',
'\\1\\2'
)
输出:
00001.00022.00333
然后就可以正常排序了。
此解决方案适用于任意数量的组件。您可以将组件长度从 5 缩放到任意固定长度。