在Yii2 ActiveRecord中使用子查询进行更新

时间:2018-06-11 10:14:55

标签: php activerecord yii2

更新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 :(得分:2)

尝试将Yii更新到最新版本。从2.0.14开始,yii\db\ExpressionInterface(包括QueryActiveQuery)的所有实例都应该正确处理,并以与yii\db\Expression类似的方式生成SQL。所以这一切应该在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中使用。

答案 1 :(得分:0)

您可以使用count()获取记录数。

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

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

答案 2 :(得分:0)

我更愿意:

$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();

ps:如果两个表都相同,则必须执行以下操作:

$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();