DBIx::Class:如何对列的多个子字符串进行排序?

DBIx::Class: How can I sort on multiple substrings of a column?

我有一个带有 table 的 SQLite 数据库,其文档编号遵循以下模式:

16-145-45
16-127-30
16-141-42
16-122-14
15-090-04
15-089-15
15-089-05

我想按数字的第一部分和最后一部分对 ResultSet 进行排序,如下所示。首先,所有以最高两位数前缀(16)开头的文档按最后两位数排序,然后与下一个块相同,依此类推。

16-145-45
16-141-42
16-127-30
16-122-14
15-089-15
15-089-05
15-090-04

有没有办法在 DBIx::Class 中使用某种自定义 order_by 子句来做到这一点,或者方法是什么?

我试过下面的方法,还是不行,因为中间的数字也要考虑排序:

my @rs = $self->search(undef,
    {
        order_by => { -desc => 'me.number' }
    }
);

如果想让数据库对结果进行排序,就得用literal SQL

这是一个 Postgres 的例子(我在反斜杠后添加了一个 space 来修复语法高亮):

my @rs = $self->search(undef,
    {
        order_by => \ "split_part(number, '-', 1) || split_part(number, '-', 3) DESC",
    }
);

或者,通过使用 +select result set attribute:

创建一个输出列
my @rs = $self->search(undef,
    {
        '+select' => [
            { sort_key => \ "split_part(number, '-', 1) || split_part(number, '-', 3)" },
        ],
        '+as' => [ qw(sort_key) ],  # Make sort key accessible from DBIC.
        order_by => { -desc => 'sort_key' },
    }
);

另一种方法是检索整个未排序的结果集,并在客户端对其进行排序。 DBIC 没有任何特定功能可以帮助您,因此只需使用 Perl 的 sort 函数即可。

您需要从结果集中提取额外的列,这些列等于您要作为排序依据的函数的值。然后你可以像往常一样将这些列放在 order_by 子句中

这假设您的 文档编号 字段称为 docnum。它从 Table 中获取所有列加上 docnum 的两个子字符串 docnum1docnum3

my $rs = $schema->resultset('Table')->search(undef,
    { 
        '+select' => [
            { substr => [ 'docnum', 1, 2 ], -as => 'docnum1' },
            { substr => [ 'docnum', -2 ],   -as => 'docnum3' },
        ],
        order_by => [ { -desc => 'docnum1' }, { -desc => 'docnum3' } ],
    }
);

由于@nwellnhof 的回答非常有效,我只是想为 SQLite 提供相应的语法,它不知道 split_part() 函数。

# SQL for filtering the doc number in SQLite

my @rs = $self->search(undef,
    {
        order_by => \ "SUBSTR(me.number, 1, 2) || SUBSTR(me.number, -2, 2) DESC"
    }
);