Yii2:从hasMany关系中选择最后一条记录

时间:2017-08-17 14:31:00

标签: php mysql yii2 yii2-advanced-app

我对mysql的了解是非常基础的,现在我正面临着一个“复杂”(对我来说)查询,其中我卡住了,所以如果有人能给我一些关于此的话,请提前感谢你。

我有三张桌子:

订单

id | name | comments | ...

OrderLines

id | name | sDate | eDate | comments | ...

OrderLinesStats

id | lineID | date | status | ...

每天通过cron作业更新OrderLinesStats并获取具有实际日期,状态和其他字段的新记录,因此最高id是实际数据。

我试图在yii2中获得具有关系的最后一个统计行,如下所示:

OrdersLines模型中的

public function getLastOrdersLinesStats()
{
    return $this->hasMany(OrdersLinesStats::className(), ['lineID' => 'id'])
        ->orderBy(['id'=>SORT_DESC])
        ->groupBy('lineID');
}

OrdersModel:

public function getOrdersLines()
    {
        return $this
            ->hasMany(OrdersLines::className(), ['orderID' => 'id'])
            ->orderBy(['typeID' => SORT_ASC, 'name' => SORT_ASC])
            ->with(['lastOrdersLinesStats']);
    }

但是当我调试查询时看起来像这样:

SELECT * FROM `ordersLinesStats` WHERE `lineID` IN (1873, 1872, 1884, 1883, 1870, 1874, 1876, 1880, 1871, 1877, 1881, 1882, 1885, 1886, 1869, 1875, 1878) GROUP BY `lineID` ORDER BY `id` DESC

并没有给我每行的最后统计记录......事实上,它给了我最老的记录。似乎我错过了一些但我无法找到它。

再次感谢

3 个答案:

答案 0 :(得分:4)

您需要做的就是将getLastOrdersLinesStats()更改为如下:

public function getLastOrdersLinesStats()
{
    return $this->hasMany(OrdersLinesStats::className(), ['lineID' => 'id'])
        ->orderBy(['id'=>SORT_DESC])
        ->one();
}

这基本上返回了每个Order

所需的最后一个OrderLinesStats行

您可以按如下方式访问:

如果你有一个名为myOrder的对象 然后您可以访问所需的行myOrder->lastOrderLinesStats

答案 1 :(得分:3)

在OrdersModel中添加使用via()结点的getLastOrderLineStat()方法:

public function getLastOrderLineStat()
{
    return $this->hasOne(OrdersLinesStats::className(), ['lineID' => 'id'])
        ->orderBy(['id'=>SORT_DESC])
        ->groupBy('lineID')
        ->via('ordersLines');
}

如果$ model是OrdersModel实例,则使用以下命令获取最后一个stat行:

$model->lastOrderLineStat

答案 2 :(得分:0)

我只是回答这个是彻底的,并希望帮助其他人偶然发现这个页面。

我建议始终同时包含hasOnehasMany。这样,您可以弹出顶部记录,或检索所有记录。

/**
 * @return \yii\db\ActiveQuery
 */
public function getUserPlan()
{
    return $this->hasOne(UserPlan::className(), ['user_id' => 'id'])
        ->orderBy(['id' => SORT_DESC])
        ->one();
}

/**
 * @return \yii\db\ActiveQuery
 */
public function getUserPlans()
{
    return $this->hasMany(UserPlan::className(), ['user_id' => 'id'])
        ->orderBy(['id' => SORT_DESC])
        ->all();
}

hasMany将返回一个ActiveQuery对象数组,其中hasOne将自动返回一个ActiveQuery对象。

您可以像这样使用它们(用户模型上的UserController中的示例):

$model = $this->findOne($id);

$model = User::findOne($id);

$model = User::find()->where(['id' => $id])->one();

然后像这样抓住关系:

$plan = $model->userPlan

$plans = $model->userPlans

对于userPlan:

$planId = $plan->id;

处理userPlans:

foreach($plans as $plan) {
    $plan->id;
}