等效的DBIx :: Class语法?

时间:2016-09-02 01:06:33

标签: mysql perl dbi dbix-class

我从这个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排序返回。

1 个答案:

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