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
的两个子字符串 docnum1
和 docnum3
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"
}
);
我有一个带有 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
的两个子字符串 docnum1
和 docnum3
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"
}
);