2011-10-13 38 views
1

給定兩個表:(傳入大大降低/簡化的示例呈現的關鍵問題)使用dbix-class加入子查詢?

app_data文件表示可以訂閱

id app_name 
1 apple 
2 berry 
3 cherry 

app_sub地圖電子郵件地址應用

應用
id email 
1 alex 
2 bob 
2 coby 

我想從單用戶的觀點生成一個表,顯示哪一個當前用戶訂閱的應用而不是。

例如,從亞歷克斯的角度來看,我想獲得:

desired_table

id app_name is_subscribed 
1 apple  true 
2 berry  false 
3 cherry  false 

以下純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; 

不過我很難讓它在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', 
          ); 

然而,該(現預期地)的結果(處理0和null作爲假後):

bad_table

id app_name is_subscribed 
1 apple  true 
3 cherry  false 

由於 '鮑勃' 和 'COBY' 訂閱ID 2,where子句完全消除了開環nd id。

任何幫助將不勝感激!

回答

-1

文森特,我想加入到一個子查詢現在我自己。到目前爲止,我找不到任何成功的人。

另一種方法是在普通SQL中用$ c-> model('blah') - > storage-> dbh-> prepare(「query」)或'通過自定義ResultSource的任意SQL'部分的DBIx類食譜,這也似乎是一個合理的方式。

+0

謝謝!我最終通過一個自定義的ResultSource來使用任意SQL。構建一個乾淨而有效的ResultSource :: View花費了不小的努力,但它絕對奏效! – vlee

4

我自己沒有去100%的任意SQL,因爲這有點吸吮。我所做的是將所述子查詢插入一些原始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 } }); 
} 

如果我在某些時候有一段時間,我會簸下來到一個更易消化的例子,但問題是,我使用DBIx ::類來生成硬查詢並手動將它們在一個小地方一起粉碎,然後將THAT包裝在子查詢中,以便我可以使用純DBIx :: Class結果集方法進行更多搜索。