2010-08-07 64 views
2

问题定义。如何在DBIx :: Class :: ResultSet上执行此搜索和order_by

我有多个用户的多个客户端。每个客户端都需要能够将自定义数据与用户相关联,搜索和排序。


数据库解决方案:

甲表Customfields限定customfields表。它有一个id和名字。 它与Userfields表(又名“属性”)具有has_many关系。

Userfields表具有用户标识,customfieldid,内容和标识。 它belongs_to的一个Useraccounts表(又名 “useraccount”)和Customfields(又名 “的CustomField”)


提出,我想选择语句:

这是实现和生产什么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'; 

在这种情况下,它们可能是从0什么...在SELECT语句×副SELECT语句和它们中的任何一个,或者都不可以希望被订购。


问题

如何实现这一目标用 - >我dbix类的ResultSet或者我如何实现与我dbix类的ResultSet搜索结果相同的搜索?

下面是我通常如何从我的Useraccounts表中选择,但我不确定如何从这里执行复杂的语句。

my @users = $db->resultset('Useraccounts')->search(
    undef, 
    { 
     page  => $page, 
     join  => 'attributes', 
     ... 
    }); 

谢谢你的时间。

-pdh

+0

我太累了,不想回答这个问题,但是男人,我必须给你一些道具来编写这样一个写得很好的问题! – 2010-08-07 09:13:04

+0

干杯JGB;希望它会鼓励一个很好的答案:) – 2010-08-07 09:22:32

回答

2

这是真的很漂亮毛茸茸的,任何解决方案不会是漂亮,但它确实如果你通融一点一下就可以了。原谅我犯的任何错误,因为我没有去创建一个模式来测试它,但它基于我拥有的最好的信息(以及来自ribasushi的很多帮助)。

首先,(假设你的userfields表具有与customfields表belongs_to的关系,称为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;如果你给它一个不同的别名,那么你会在这里使用不同的东西。 无论如何,只要改变字段名称(如果你聪明的话,你会写一个方法来生成它们),并将它们放在一个数组中,就可以重复这个业务。现在让我们假设@field_queries是一个数组,包含上面的$mbd以及另一个基于Join Date的数组,以及任何您喜欢的数据。

一旦你的,它是“简单”为...

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(BE注意SQL注入这里!!),这将回避占位符错误。但在不久的将来,该错误将得到解决,上面的代码将正常工作,我们将更新答案,让您知道是这种情况。

+0

非常感谢Hobbs(和Ribasushi):)。 在这么短的时间里,这比我所希望的要多:D。很荣幸给你:) – 2010-08-07 11:46:05

+0

两点。 1) - > get_column('content') - > as_query;返回一个对数组引用的引用,而不是对数组的引用,这可能是我当前dbix :: class中的一个错误,但是我看不到更改日志中提到的任何修复,文档似乎表明这是预期的行为!我解决了这个问题 $ {userfields_rs-> search(...)} 2)我解决了占位符问题,在我的搜索中加入了 'bind'=> $ mbd - > [1] 。 在今天早上玩了很多游戏后,它的所有功能:) – 2010-08-09 13:19:23

+0

轻微的问题,如果我调用 - >对结果集进行分页,我无法获取 - > total_entries,它看起来像抓住它不需要的占位符,将它们追加到最后,这会导致错误。现在用eval来解决这个问题,但这很丑陋。 – 2010-08-12 14:58:53

相关问题