如何在蛋糕php 3中在Group by之前执行Order by?

Posted

技术标签:

【中文标题】如何在蛋糕php 3中在Group by之前执行Order by?【英文标题】:How to execute Order by before Group by in cake php 3? 【发布时间】:2017-08-14 12:35:41 【问题描述】:

我正在获取用户给出的所有答案。但我只需要用户的最新答案/响应(使用响应 id)。我正在运行以下查询。

$users_all_answers=$this->SurveySectionAnswers->find('all')
                             ->where(['survey_response_id IN'=>$response_ids])
                             ->order(['survey_response_id'=>'desc'])
                             ->group(['survey_question_id'])
                             ->hydrate(false)
                             ->toArray();

但我得到的是用户的回答,而不是最新的响应,因为在 Order by 之前在 Group by 上执行。那么是否有任何解决方案,以便我可以通过用户的最新回复获得所有答案。

像这样获取数组

[0] => Array
    (
        [id] => 527
        [survey_response_id] => 74
        [survey_question_id] => 84
        [survey_answer] => 
        [survey_score] => 0
        [survey_section_id] => 50
        [survey_answer_id] => 138
        [completed] => 1
    )

[1] => Array
    (
        [id] => 528
        [survey_response_id] => 74
        [survey_question_id] => 85
        [survey_answer] => 
        [survey_score] => 0
        [survey_section_id] => 48
        [survey_answer_id] => 142
        [completed] => 1
    )

但我想要喜欢

[0] => Array
    (
        [id] => 527
        [survey_response_id] => 76
        [survey_question_id] => 84
        [survey_answer] => 
        [survey_score] => 0
        [survey_section_id] => 50
        [survey_answer_id] => 138
        [completed] => 1
    )

[1] => Array
    (
        [id] => 528
        [survey_response_id] => 76
        [survey_question_id] => 85
        [survey_answer] => 
        [survey_score] => 0
        [survey_section_id] => 48
        [survey_answer_id] => 142
        [completed] => 1
    )

【问题讨论】:

您不能在mysql 中执行此操作,您可以使用 max/min 函数并将其与 group by function 混合,或者使用子查询获取最新答案然后订购,或者使用 php它自己在获取数据后对其进行排序; 【参考方案1】:

在 MySQL 中,GROUP BY 在 ORDER BY 之前执行。 GROUP BY 将始终选择结果集中的顶行,因此在执行该组之前它不受 ORDER BY 的影响。

有一个 number of techniques 可以执行您在 MySQL 中描述的操作。我更喜欢使用将表连接到自身的方法,以确保最新的行是实际选择的行。

在 CakePHP 中看起来像这样:

$users_all_answers = $this->SurveySectionAnswers->find()
    ->join([
        'SurveySectionAnswers_2' => [
            'table' => 'survey_section_answers',
            'type' => 'LEFT',
            'conditions' => [
                'SurveySectionAnswers_2.survey_question_id' => new \Cake\Database\Expression\IdentifierExpression('SurveySectionAnswers_2.survey_question_id'),
                'SurveySectionAnswers.id <' => 'SurveySectionAnswers_2.id'
            ]
        ]
    ])
    ->where([
        'SurveySectionAnswers.survey_response_id IN' => $response_ids,
        'SurveySectionAnswers_2 IS ' => null
    ])
    ->hydrate(false)
    ->toArray();

之所以有效,是因为 LEFT JOIN 按顺序列出了所有可能的行组合,但 WHERE 子句过滤了结果集中除了最近的(没有连接的行)之外的所有组合。

【讨论】:

【参考方案2】:

另一种选择是使用Collections indexBy 或groupBy。

这会产生性能影响,但在代码中可能会更清晰。

获取您的答案列表。这将返回一个带有集合接口的对象。

$users_all_answers = $this->SurveySectionAnswers->find('all')
                         ->where(['survey_response_id IN'=>$response_ids])
                         ->order(['survey_response_id'=>'asc'])
                         ->hydrate(false);

请务必注意,您必须以相反的顺序对查询进行排序,因为 indexBy 和 groupBy 将返回组中的最后一项

在上述查询中,我将survey_response_id 的顺序从desc 更改为asc 以完成此操作。

然后您可以在有序查询上调用 groupBy 或 indexBy。这将立即调用您的查询。

$users_grouped_by_id = $users_all_answers->groupBy('survey_question_id')

或者,如果您只希望每组 1 个结果

$users_indexed_by_id = $users_all_answers->indexBy('survey_question_id')

groupByindexBy 是集合接口函数。不要与group 混淆,后者是一个查询构建器功能。每个查询都是一个集合,但集合不是查询。

【讨论】:

以上是关于如何在蛋糕php 3中在Group by之前执行Order by?的主要内容,如果未能解决你的问题,请参考以下文章

HABTM 蛋糕 php 查找

mysql 可以group by 两个字段吗

mysql group by 能用到索引么

使用 CTE 在 Group by 之前或之后过滤

从 3 个表中选择,在两个 group by 之前有两个 order by

如何在 GROUP BY 之前对 Core Data 记录进行排序?