我从这个question获得了这个mysql查询。
SELECT a.*
FROM products a
INNER JOIN product_tags b ON a.product_id = b.product_id
WHERE b.tag_id IN (1,23,54)
GROUP BY a.product_id
HAVING COUNT(1) = 3
我想知道如何将其转换为DBIx::Class语法?
来自DBIx文档,这就是关于联接的内容,但我不确定如何合并它?
确定联合和关系^
在DBIx :: Class中,需要首先在表的ResultSource中定义两个表之间的每个关系。如果需要在两个方向上访问关系(即获取CD的所有轨道,并获取轨道的CD数据),则需要为两个表定义它。
对于CD / Tracks示例,这意味着在MySchema :: CD中写作:
MySchema::CD->has_many('tracks', 'MySchema::Tracks');
在MySchema :: Tracks:
MySchema::Tracks->belongs_to('cd', 'MySchema::CD', 'CDID');
还有其他几种类型的关系,它们在DBIx :: Class :: Relationship中有更全面的描述。 使用JOINS ^
一旦定义了所有关系,在实际连接中使用它们就相当简单。您选择的关系类型,例如has_many,已经指示将执行什么类型的连接。例如,has_many生成一个LEFT JOIN,它将获取左侧的所有行,右侧是否有匹配的行(正在连接的表),或者没有。您可以在关系中强制使用其他类型的连接,请参阅DBIx :: Class :: Relationship文档。
执行搜索或查找操作时,您可以使用join属性指定哪些关系也可以根据以下内容优化结果:
$schema->resultset('CD')->search(
{ 'Title' => 'Funky CD',
'tracks.Name' => { like => 'T%' }
},
{ join => 'tracks',
order_by => ['tracks.id'],
}
);
如果您不认识这种语法的大部分内容,那么您应该阅读"搜索"在DBIx :: Class :: ResultSet和" ATTRIBUTES"在DBIx :: Class :: ResultSet中,但这里有一个快速分解:
搜索的第一个参数是WHERE属性的hashref,在这种情况下是CD表中Title列的限制,以及Tracks表中轨道名称的限制,但仅适用于实际相关的轨道选择的CD。第二个参数是搜索属性的hashref,结果将按相关轨道的id排序返回。
答案 0 :(得分:2)
首先,你要定义一个来自产品的标签。
MySchema::Result::Product->has_many(
'tags', 'MySchema::Result::ProductTag', 'product_id'
);
定义来自标签的产品:
MySchema::Result::ProductTag->belongs_to(
'products', 'MySchema::Result::Product', 'product_id'
);
如果您正在使用Schema :: Loader,则已经推断出这些。 (无耻的插件:以上会更短,更甜美的DBIx :: Class :: Candy和DBIx :: Class :: Helper :: Row :: RelationshipDWIM)
现在复制原始查询:
$schema->resultset('Product')->search({
tags.tag_id => { -in => [1,23,54] },
}, {
join => 'tags',
group_by => 'me.product_id',
having => { 'count 1' => 3 },
})