问题定义。
我有多个客户端和多个用户。每个客户端都需要能够将自定义数据与用户、搜索和排序依据相关联。
数据库解决方案:
表
Customfields
定义 customfields
表。它有一个 id
和 name
。
它与 Userfields
表(又名“属性”)有 has_many 关系。
Userfields
桌子有userid
、customfieldid
、content
和id
。
它属于 Useraccounts
表(又名“用户帐户”)和 Customfields
(又名“自定义字段”)
我想要的建议选择语句:
这是一个 select 语句,可以实现并生成我需要的内容。
SELECT ua.*, (
SELECT content FROM Userfields uf
INNER JOIN Customfields cf
ON cf.id = uf.customfieldid
WHERE cf.name = 'Mothers birthdate'
AND uf.uid=ua.uid
) AS 'Mothers birthdate',
(
SELECT content FROM Userfields uf
INNER JOIN Customfields cf
ON cf.id = uf.customfieldid
WHERE cf.name = 'Join Date' AND
uf.uid=ua.uid
) AS 'Join Date'
FROM UserAccounts ua
ORDER BY 'Mothers birthdate';
在这种情况下,它们可以是 select 语句中 0 ... x 子 SELECT 语句中的任何内容,并且它们中的任何一个或它们都可能不希望被排序。
问题
如何在 DBIx 类结果集上使用
->search
实现此目的,或者如何在 DBIx 类结果集上使用 ->search
实现相同的结果?
这是我通常从我的
Useraccounts
表中进行选择的方式,尽管我不确定如何从这里执行我想要的复杂语句。
my @users = $db->resultset('Useraccounts')->search(
undef,
{
page => $page,
join => 'attributes',
...
});
这确实很棘手,任何解决方案都不会很漂亮,但如果你稍微改变一下规则,它确实看起来是可能的。请原谅我犯的任何错误,因为我没有去创建一个模式来测试它,但它是基于我拥有的最佳信息(以及 ribasushi 的帮助)。
首先,(假设您的 userfields 表与 customfields 表有属于关系,称为
customfield
)
my $mbd = $userfields_rs->search(
{
'customfield.name' => 'Mothers birthdate',
'uf.uid' => \'me.uid' # reference to outer query
},
{
join => 'customfield',
alias => 'uf', # don't shadow the 'me' alias here.
}
)->get_column('content')->as_query;
# Subqueries and -as don't currently mix, so hack the SQL ourselves
$mbd->[0] .= q{ AS 'Mothers Birthdate'};
uf.uid 匹配的文字
me.uid
是一个未绑定变量——它是查询中的 uid
字段,我们最终将把这个查询作为子选择放入其中。默认情况下,DBIC 为查询所寻址的表设置别名 me
;如果你给它一个不同的别名,那么你会在这里使用不同的东西。
不管怎样,你可以用任意数量的不同字段重复这个as_query
业务,只需改变字段名称(如果你很聪明,你将编写一个方法来生成它们),并将它们放入一个数组中,所以现在让我们假设 @field_queries
是一个数组,包含上面的 $mbd
以及另一个基于加入日期的数组,以及您喜欢的任何内容。
一旦你有了它,它就“简单”了......
my $users = $useraccounts_rs->search(
{ }, # any search criteria can go in here,
{
'+select' => [ @field_queries ],
'+as' => [qw/mothers_birthdate join_date/], # this is not SQL AS
order_by => {-asc => 'Mothers birthdate'},
}
);
这会将每个子查询包含到选择中。
现在是悲伤的部分:截至目前,整个事情实际上不会工作,因为带有占位符的子查询无法正常工作。因此,现在您需要一个额外的解决方法:在子选择搜索中不要使用
'customfield.name' => 'Mothers birthdate'
,而是执行 'customfield.name' => \q{'Mothers birthdate'}
——这是使用文字 SQL 作为字段名称(这里的 SQL 注入请小心!),这将避免占位符错误。但在不久的将来,该错误将得到解决,上面的代码将正常工作,我们将更新答案,让您知道情况确实如此。
请参阅 DBIx::Class::ResultSource order_by 文档