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.
任何帮助将不胜感激!
我自己做了这个没有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结果集方法进行更多搜索.