使用dbix-class加入子查询?

vle*_*lee 1 sql perl subquery dbix-class

给出两个表:(表示关键问题的传入大大减少/简化的示例)

app_data表示可以订阅的应用程序

id   app_name
 1   apple
 2   berry
 3   cherry
Run Code Online (Sandbox Code Playgroud)

app_sub将电子邮件地址映射到应用程序

id   email
 1   alex
 2   bob
 2   coby
Run Code Online (Sandbox Code Playgroud)

我想从单用户的角度生成一个表,显示当前用户订阅的应用程序,而不是.

例如,从Alex的角度来看,我想得到:

desired_table

id    app_name    is_subscribed
 1    apple       true
 2    berry       false
 3    cherry      false
Run Code Online (Sandbox Code Playgroud)

以下纯SQL查询似乎没问题:

select id, app_name, email
  from app_data left join ( select *
                              from app_sub
                             where email='alex'
                          ) as subquery
                          on app_name.id=app_data.id;
Run Code Online (Sandbox Code Playgroud)

但是我很难在dbix-class中工作.

或者,我试图消除子查询,如下所示:

$app_data_resultset->search( { -or => [ { email => 'alex' },
                                        { email => undef },
                                      ],
                             },
                             { select => [ qw{ me.id
                                               me.app_name
                                               app_sub.email
                                             },
                                         ],
                               as => [ qw{ id
                                           app_name
                                           email
                                         },
                                     ],
                               join => 'app_sub',
                           );
Run Code Online (Sandbox Code Playgroud)

但是,这(现在预期)导致以下结果(在将0和null都视为false之后):

bad_table

id    app_name    is_subscribed
 1    apple       true
 3    cherry      false
Run Code Online (Sandbox Code Playgroud)

由于'bob'和'coby'订阅了id 2,因此where子句完全消除了第二个id.

任何帮助将不胜感激!

Fre*_*idt 5

我自己做了这个没有100%任意SQL,因为IMO有点糟透了.我所做的是将所述子查询插入到一些原始SQL中,然后使用来生成更多查询.所以这是我的例子(来自https://github.com/frioux/drinkup/blob/master/lib/DU/Schema/ResultSet/Drink.pm#L164):

sub ineq {
   my ($self, $ingredient_rs, $min, $max) = @_;

   my $ingredients_on_hand = $ingredient_rs
      ->search(undef, {
         join => { kind_of => 'links_to_drink_ingredients' },
         columns => {
            drink_id => 'links_to_drink_ingredients.drink_id',
            ingredient_count => { count => '*', -as => 'ingredient_count' },
         },
         group_by => 'links_to_drink_ingredients.drink_id',
      })->as_query;


   my $required_ingredients = $self->result_source->schema->resultset('Drink_Ingredient')
      ->search(undef, {
         columns => {
            drink_id => 'me.drink_id',
            ingredient_count => { count => '*', -as => 'ingredient_count' },
         },
         group_by => 'me.drink_id',
      })->as_query;

   my ($ioh_sql, @ioh_bind) = @{$$ingredients_on_hand};
   my ($ri_sql, @ri_bind) = @{$$required_ingredients};

   my $creation = \[
   <<"SQL",
      SELECT di.drink_id FROM (
         $ri_sql di,
         $ioh_sql ii
      )
      WHERE di.drink_id = ii.drink_id AND
            di.ingredient_count >= ii.ingredient_count + ? AND
            di.ingredient_count <= ii.ingredient_count + ?
SQL
   @ri_bind, @ioh_bind, [{ sqlt_datatype => 'int' } => $min], [{ sqlt_datatype => 'int' } => $max] ];

   $self->search({ 'me.id' => { -in => $creation } });
}
Run Code Online (Sandbox Code Playgroud)

如果我在某些时候得到一些时间,我将把它变成一个更容易理解的例子,但重点是我使用DBIx :: Class来生成硬查询并在一个小地方手动粉碎它们,然后包装THAT在子查询中,以便我可以使用简单的DBIx :: Class结果集方法进行更多搜索.