使用Yii framework 2.0,我有两个数据库表(A和B)。它是一个关系数据库1:n。 A只有一个B,但B有很多A.我的数据库看起来与此类似。
A table:
id = 1, name = yes
id = 2, name = no
id = 3, name = ok
id = 4, name = good
B table:
id = 1, a_id = 1
id = 2, a_id = 1
id = 3, a_id = 2
我想从' A'中检索记录。其主键未出现在' B'表。我想得到的结果是。
A table:
id = 3, name = ok
id = 4, name = good
我不想使用以下代码,因为它对我来说效率不高。
$allA = A::find()->all();
foreach($allA as $model) {
if(!$model->getBs()) {
$allAWithoutB[] = $model;
}
}
如何定义这样的关系方法或范围BQuery类,以便我不需要查询所有A记录并在for-each循环中过滤它们?
答案 0 :(得分:1)
我认为这种逻辑不适合关系。
您可以将查询与子查询一起使用。首先从a_id
表中选择所有唯一b
,然后从a
表中选择中将其排除。将此方法放在AModel
。
public function getOtherModels()
{
$subquery = BModel::find()->select('a_id')->distinct()->all();
return static::find()->where(['not in', 'id', $subquery]);
}
如果您愿意,可以将其放在scope中。
答案 1 :(得分:1)
arogachev发布的答案几乎正确。
如果您要运行他的方法getOtherModels()
,您将获得“无法将对象转换为字符串”#39;异常。
我的方法完全相同,除了我已经使用方法static
并添加了foreach
来遍历对象并将a_id
值添加到新数组中。 / p>
我还在方法中添加了$condition
参数,因此您可以为A模型添加条件。
/**
* @return \yii\db\ActiveQuery
*/
public static function withoutBModel($condition = null)
{
$subquery = BModel::find()->select('a_id')->distinct()->all();
$arr = [];
foreach ($subquery as $q) {
$arr[] = $q->a_id;
}
$query = static::find()->where(['not in', 'id', $arr]);
if (!empty($condition)) {
$query->andWhere($condition);
}
return $query;
}
使用此方法如下:
$aModelsWithoutB = A::withoutBModel('active = 1')->all();