这一定是一件简单的事情,但即使在 Stackoverflow 上查看很多示例,我也无法弄清楚。
我有这个字符串序列,由 SQLite select 生成:
SELECT sort FROM collections ORDER BY sort
1
10
11
14
15
2
3
4
5
6
6.12
6.7
6.7.13
6.7.8
9
但我需要按这个顺序(内容排序就像版本号):
1
2
3
4
5
6
6.7
6.7.8
6.7.13
6.12
9
10
11
14
15
请问如何使用 SQLITE 3 select 执行此操作? 最好的问候
SQL 中的版本排序并不容易。在 SQLite 中就更难了,因为它没有很多函数来进行字符串处理(没有拆分)。
如果数据不是太多,可以使用检索数据的编程语言来完成。这是一个问题,因为它要求您将所有数据提取到内存中。
您可以向 SQLite 提供您自己的自定义排序规则。如何执行此操作取决于您用来运行查询的编程语言和驱动程序。这是使用 Perl 和 DBD::SQLite 的示例。
use DBD::SQLite;
require version;
$DBD::SQLite::COLLATION{as_versions} = sub {
my($a,$b) = @_;
return version->parse($a) <=> version->parse($b);
};
my $dbh = DBI->connect(...);
my $sth = $dbh->prepare(q{
SELECT sort
FROM collections
ORDER BY sort COLLATE as_versions
});
最后,您可以将数据更改为更适合 SQLite 的形式。插入版本时,添加另一列,该列是转换为数字的版本。这通常是通过将每个部分转换为千分之一、百万分之一、十亿分之一等来完成的。例如,“6.7.13”变为“6.007013”,“6.12”变为“6.012”。
此查询将字符串版本解析为带有 int versions 的三列,并按升序对版本号进行排序,从主版本号到内部版本号。
SELECT *,
CAST(SUBSTR(version, 1, INSTR(version, '.')-1) AS INTEGER) AS major,
CAST(SUBSTR(SUBSTR(version, INSTR(version, '.')+1) , 1, INSTR(SUBSTR(version, INSTR(version, '.')+1), '.')-1) AS INTEGER) AS minor,
CAST(SUBSTR(SUBSTR(version, INSTR(version, '.') + 1) , INSTR(SUBSTR(version, INSTR(version, '.') + 1) , '.') + 1) AS INTEGER) AS build
FROM collections
ORDER BY major DESC, minor DESC, build DESC
我采取了一种更直接的方法。我不喜欢多个查询嵌套,但我没有看到这样的性能明显下降:
SELECT
Id,
Major,
Minor,
CAST(Version AS integer) Build,
CAST(SUBSTR(Version, INSTR(Version, '.') + 1) AS integer) Revision
FROM (
SELECT
Id,
Major,
CAST(Version AS integer) Minor,
SUBSTR(Version, INSTR(Version, '.') + 1) Version
FROM (
SELECT
Id,
CAST(Version AS integer) Major,
SUBSTR(Version, INSTR(Version, '.') + 1) Version
FROM
Releases
)
)
我将其制作成一个视图,以便我可以将其附加回需要根据其他外部关系进行排序的表。
从此:
对此:
可以说,它比不断增加的子子字符串调用沿着版本八位组移动更容易理解和维护。