Использование подзапроса для обновления в Yii2 ActiveRecord - PullRequest
0 голосов
/ 11 июня 2018

Можно ли использовать подзапрос при обновлении ActiveRecord?

У меня есть таблица products со следующими столбцами

id    number_of_orders
1           3
2           3
3           2

и items таблица

id    product_id
1         1
2         1
3         1
4         2
5         2
6         2
7         3
8         3

Я хочу

UPDATE products
SET number_of_orders = (
    SELECT COUNT(id) FROM items WHERE product_id = 1
)
WHERE id = 1

Я пробовал

$subquery = ItemsModel::find()
    ->select('COUNT(id)')
    ->where(['product_id' => 1]);

ProductsModel::updateAll(
    [
        'number_of_orders' => $subquery
    ],
    [
        'id' => 1
    ]
);

и

$product = ProductsModel::findOne(1);
$product->number_of_orders = $subquery;

$product->save();

, но ни один изэто сработает.

Кто-нибудь имеет представление о решении этой проблемы?

Вывод:

Каждый из двух способов работаеточень хорошо после того, как я обновил до yii 2.0.14.

Ответы [ 3 ]

0 голосов
/ 11 июня 2018

Попробуйте обновить Yii до последней версии.Начиная с 2.0.14 все экземпляры yii\db\ExpressionInterface (включая Query и ActiveQuery) должны обрабатываться правильно и генерировать SQL аналогично yii\db\Expression.Так что все это должно работать в Yii 2.0.14 или более поздней версии:

$subquery = ItemsModel::find()
    ->select('COUNT(id)')
    ->where(['product_id' => 1])

ProductsModel::updateAll(
    ['number_of_orders' => $subquery],
    ['id' => 1]
);

$product = ProductsModel::findOne(1);
$product->number_of_orders = $subquery;
$product->save();

ProductsModel::updateAll(
    ['number_of_orders' => new Expression('SELECT COUNT(id) FROM items WHERE product_id = 1')],
    ['id' => 1]
);

Последний пример должен работать и в более ранних версиях Yii.

0 голосов
/ 11 июня 2018

Я бы предпочел:

$model = ProductsModel::findOne(1);
$model->updateAttributes(['number_of_orders' => ItemsModel::find()->where(['product_id' => 1])->count()]);

или вы можете сделать

$query = Yii::$app->db
        ->createCommand(sprintf('UPDATE %s SET number_of_orders=(SELECT COUNT(*) FROM %s WHERE product_id=:id) WHERE id=:id', ProductsModel::tableName(), ItemsModel::tableName()), [':id' => $id, ])
        ->execute();

пс: если обе таблицы одинаковы, вы должны сделать:

$query = Yii::$app->db
        ->createCommand(sprintf('UPDATE %s SET number_of_orders=(SELECT * FROM (SELECT COUNT(*) FROM %s WHERE product_id=:id) xxx) WHERE id=:id', ProductsModel::tableName(), ItemsModel::tableName()), [':id' => $id, ])
        ->execute();
0 голосов
/ 11 июня 2018

Вы можете использовать count () для получения количества записей.

$itemCount = ItemsModel::find()
   ->where(['product_id' => 1]);
   ->count();

$product = ProductsModel::findOne(1);
$product->number_of_orders = $itemCount;
$product->save();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...