присоединиться к подзапросу с dbix-классом? - PullRequest
1 голос
/ 14 октября 2011

С учетом двух таблиц: (входящий сильно уменьшенный / упрощенный пример, который демонстрирует ключевую проблему)

app_data представляет приложения, на которые можно подписаться

id   app_name
 1   apple
 2   berry
 3   cherry

app_sub сопоставляет адреса электронной почты с приложениями

id   email
 1   alex
 2   bob
 2   coby

Я хотел бы создать таблицу из однопользовательской точки зрения, показывающую, на какие приложения подписан текущий пользователь, а на какие нет.

Например, с точки зрения Алекса, я хотел бы получить:

требуемый_таблицы

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-классе.

В качестве альтернативы я попытался удалить подзапрос следующим образом:

$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, так и нуля как ложного):

bad_table

id    app_name    is_subscribed
 1    apple       true
 3    cherry      false

Поскольку 'bob'и 'coby' подписаны на id 2, предложение where полностью исключаетВторой идентификатор.

Любая помощь будет принята с благодарностью!

Ответы [ 2 ]

5 голосов
/ 16 октября 2012

Я сделал это сам, не переходя на 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 } });
}

Если в какой-то момент у меня будет время, я приведу это к более удобному примеру, но суть в том, что я использую DBIx :: Class для генерации сложных запросов и их ручного объединения в одном небольшом месте, и затем оберните это в подзапрос, чтобы я мог просто использовать простые методы набора данных DBIx :: Class для дополнительных поисков.

0 голосов
/ 17 октября 2011

Винсент, я сейчас пытаюсь присоединиться к подзапросу. Я пока не могу найти никого, кто преуспел.

Альтернативой является просто сделать это в простом SQL с $ c-> model ('blah') -> storage-> dbh-> prepare ("query") ИЛИ разделом "Произвольный SQL через пользовательский ResultSource" Поваренная книга класса DBIx, которая также кажется разумным способом.

...