Работая с 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?
Ответ, который опубликовал арогачев, почти правильный.
Если бы вы должны были запустить его метод getOtherModels()
вы получите исключение «Невозможно преобразовать объект в строку».
Мой метод ниже делает то же самое, за исключением того, что я сделал метод static
и добавил foreach
перебрать объекты и добавить a_id
значения в новый массив.
Я также добавил $condition
аргумент метода, так что вы можете добавить условия для моделей А.
/**
* @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();
Я думаю, что логика не подходит для отношений.
Вы можете использовать запрос с подзапросом. Прежде всего выберите все уникальные a_id
от b
таблицы, а затем исключить его из a
Таблица. Поместите этот метод в свой AModel
,
public function getOtherModels()
{
$subquery = BModel::find()->select('a_id')->distinct()->all();
return static::find()->where(['not in', 'id', $subquery]);
}
Вы можете положить это в объем если ты хочешь.