等价的DBIx::Class语法



我从这个问题得到了这个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::类语法?

从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中有更全面的描述。使用join ^

一旦定义了所有关系,在实际连接中使用它们就相当简单了。您选择的关系类型(例如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中的"search"和DBIx::Class::ResultSet中的"ATTRIBUTES",但这里有一个快速分解:

搜索的第一个参数是WHERE属性的hashref,在本例中是对CD表中Title列的限制,以及对Tracks表中音轨名称的限制,但仅针对与所选CD实际相关的音轨。第二个参数是搜索属性的hashref,返回的结果将按相关曲目的id排序。

首先在product的标签上定义一个rel。

 MySchema::Result::Product->has_many(
    'tags', 'MySchema::Result::ProductTag', 'product_id'
 );

从标签中定义产品的rel:

 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 },
})

最新更新