Yii2,在连接中合并两个活动查询条件

Yii2, merge two active query condictions in a join

在我的一个项目中,我有两个实体在我的数据库中表示为表。

  1. 实体A(从现在开始叫A)
  2. 实体B(从现在开始调用B)

实体 A 与 B 有 1:n 关系。

我使用 yii2 创建了两个具有关系的 ActiveRecord 模型(gii 自动创建)。

在我项目的某个控制器中,我生成(通过模型函数)两个活动查询:

$query1 = \app\models\A::generateQuery(); // Return \app\models\A::find()->where([//condictions for A])

$query2 = \app\models\B::generateQuery(); // Return \app\models\B::find()->where([//condictions for B])

在找到我想要的结果之前,加入两个实体并连接两者的 where 条件,但将它们保持为独立的活动查询。

理想的命令表示应该是:

$query1->join($query2);

sql 结果应该是这样的:

SELECT * 
FROM A JOIN B ON a.id = b.rif_a_entity 
WHERE a.field = 1 AND b.field = 2

我试过 joinWith 方法,但它似乎对我的情况不起作用。 有人遇到过类似的问题吗?

感谢大家的帮助

您可以使用 leftJoin 通过以下方式实现此目的

app\models\A::find()
->leftJoin('{{%B}}', '{{%A}}.[[id]] = {{%B}}.[[rif_a_entity]]')
->where(['=','{{%A}}.[[field]]',1])
->andWhere(['=','{{%B}}.[[field]]',1])
->all();

验证上面的查询是否生成正确的sql你需要删除 ->all() 从最后一行替换为 ->createCommand()->rawSql 并回显整个查询,如下所示并进行相应调整。您可以在 phpmyadmin window 中复制 SQL 和 运行 来验证结果集

app\models\A::find()
->leftJoin('{{%B}}', '{{%A}}.[[id]] = {{%B}}.[[rif_a_entity]]')
->where(['=','{{%A}}.[[field]]',1])
->andWhere(['=','{{%B}}.[[field]]',1])
->createCommand()->rawSql;

编辑

因为在讨论后您希望将查询分开并且不想使用上面提出的解决方案,我建议您使用 joinWith 而不是尝试 merge/join 2 ActiveQuery 您尝试执行的对象,在 Yii1 中以某种方式支持 CDbCriteria::merge() 但在 Yii2 中,对象合并已替换为 joinWithRelations,所以当您想重新使用其中一个查询中的 where 子句并希望加入该 table 时,您可以执行以下操作。

假设我们有两个模型 ProductsCategoryProducts 有 foreign_key cat_id。我会将模型 Category 中的关系定义为 hasMany()

public function getProducts(){
    return $this->hasMany(Products::className(),['cat_id'=>'id']);
}

那么假设我和你有同样的情况,我想将这两个查询分开,同时,我想加入 CategoryProducts 并使用where 现有 Products 模型查询的条件。

$cat=app\models\Category:find()->where(['=','status',1]);
$prod=app\models\Products:find()->where(['=','status',1]);

//in the first line below products is the name of the relation 
//and the second line is  how you merge the where clause from the $prod query with $cat query
$cat->joinWith(['products'])
->andWhere($prod->where);

如果您尝试查看到目前为止构建了什么查询,请将 createCommand()->rawSql 添加到上面。

$cat->joinWith(['products'])
->andWhere($prod->where)
->createCommand()
->rawSql;

这将输出以下查询

SELECT `category`.* FROM 
`category` 
LEFT JOIN 
`products` ON `products`.`cat_id` = `category`.`id` 
WHERE (`category`.`status` = 1) AND (`products`.`status` = 1)

希望这能解决您的问题