Perl DBIC用于动态创建的一组条件中的嵌套查询

时间:2017-06-16 22:42:19

标签: mysql perl catalyst dbix-class

INTRO

我正在处理复杂的表单,以便对相当大的数据库执行自定义查询。因为用户可以使用一个或多个字段进行搜索,所以我决定使条件动态化,例如:

my $where{};


if($some_param && some_param ne ''){
  push @{ $attr->{join} }, { 'aref' => { 'a_deeper_ref' => 'a_much_deeper_ref' }};
  $where->{a_much_deeper_ref.field} = [-and => $some_param, {'!=', undef}];
}

if($another_param && $another_param ne '') {
... # same thing: do the join > build the condition.
}

my $rs = $model->search ($where, $attr);

大约有40到50个字段,虽然我可以像上面那样解决大部分字段,但有些字段有点棘手......

**问题**

我将使用有问题的示例来使其更清晰。 Supose yuo有一个laboratory_exams表,其中的行表明给定的主题/患者[subject表的外键]已针对给定的临床检查进行了测试[clinical_exam的外键table]并存储该测试的结果。

现在,当用户想知道哪些受试者已经接受过艾滋病毒和丙型肝炎检测,并且艾滋病毒检测结果为阴性,丙型肝炎检测结果为阳性;表单提交将创建一个包含exam_idsresults的数组,我可以在控制器中轻松检索

my $params = $c->req->parameters;
my @labexams = ref $params->{exam_ids} ? @{$params->{exam_ids}} : $params->{exam_ids};
my @results = ref $params->{results} ? @{$params->{results}} : $params->{results};

当然,当我尝试在循环数组的$where哈希中保存条件时,它会覆盖前一个并且我最终只得到数组中的最后一个元素,因为......

foreach my $i (0 .. $#labexams){
 $where->{'labexams.exam_id'} = $labexams[$i];
 $where->{'labexams.result'} = $results[$i];
}

...而且我只是继续将条件写在' labexams.exam_id'或者' labexams.result',这是静态的。

请注意,我需要生成的SQL与

类似
... WHERE (labexams.exam_id = $labexam[$i] AND labexams.result = $result[$i]) AND ... #repeat for every exam/result pair

实际问题

我怎样才能实现这一点?

2 个答案:

答案 0 :(得分:0)

使用ResultSet搜索链功能,而不是自己构建复杂参数。

my $ rs = ResultSet('Foo') - > search(...); $ rs = $ rs-> search(...);

答案 1 :(得分:-1)

我最终为子查询构建了一个SQL表达式,并将其作为对$ where哈希的引用传递。像魅力< 3

一样工作
  if ($params->{labexam} && $params->{labexam} ne '' ){
  my @labexams = ref $params->{labexam} ? @{$params->{labexam}} : $params->{labexam};
  my @labexam_res = ref $params->{labexam_result} ? @{$params->{labexam_result}} : $params->{labexam_result};
  my $exp_sql;
  push @{ $attr->{join} }, 'laboratory_exams';

  foreach my $i (0 .. $#labexams){
    if($i == 0) {
      $exp_sql .= ' IN ';
    } else {
      $exp_sql .= ' AND laboratory_exams.subject_id IN ';
    }
    $exp_sql .= '(SELECT subject_id FROM laboratory_exams WHERE exam_id = "'.$labexams[$i].'" AND value = "'.$labexam_res[$i].'")';
    $i++;
  }
  $where->{'laboratory_exams.subject_id'} = \$exp_sql;
}