Doctrine——选择所有字段并按其中一个分组

phi*_*ipp 5 php symfony doctrine-orm

我正在尝试创建一个带有学说的查询,它在 SQL 中基本上应该是这样的:

SELECT p.* FROM some_tabel AS p GROUP BY p.type;
Run Code Online (Sandbox Code Playgroud)

所以我结束了这个,因为这是我发现记录的最接近的:

private function getAll()
{
    //$this->em => Entity Manager
    return $this->em->createQueryBuilder()
        ->select('p')
        ->from('AppBundle:Robots', 'p')
        ->groupBy('p.type')
        ->getQuery()
        ->getResult(Query::HYDRATE_ARRAY);
}
Run Code Online (Sandbox Code Playgroud)

该错误告诉我未选择“p.type”。

我怎样才能让它工作?

更新

正如@Felippe Duarte接受的答案中提到的,Mysql 的分组似乎是一种有线。即使我运行:

SELECT p.*, max(p.id) FROM some_tabel AS p GROUP BY p.type;
Run Code Online (Sandbox Code Playgroud)

正如许多答案所建议的那样,结果不是我所期望的,因为只包含每种类型的第一项,并且没有发生真正的分组。

订购而不是分组的选项很好,但仍然会给我留下一些处理,所以在这种情况下它是多余的。

最后这段代码做了我需要的:

private function groupByType(array $robots)
{
    return array_reduce($robots, 
        function($list, $robot)
        {
            $list[$robot->getType()][] = $robot;
            return $list;
        }, []);
}
Run Code Online (Sandbox Code Playgroud)

由于这不是太多代码,而且不会有太多»机器人«,我决定 - 遵循 KISS 范式 - 这是首选的解决方案。

Fel*_*rte 3

您不能按单个列进行分组,然后选择其他列。MySQL 有这个“bug”,它允许用户在选择多列的同时按一列进行分组。

换句话说,您必须使用group by所有未使用聚合函数的列,例如 SUM、AVG、MAX、COUNT。

MySQL 的这个“功能”的副作用是,它将返回其他列的第一个结果,即使它并不代表事实。

试试这个脚本:

create table test(id int, name char(1), value1 int);

insert into test values(1, 'a', 1);
insert into test values(2, 'b', 1);

select name, value1, max(id) from test group by value1;
Run Code Online (Sandbox Code Playgroud)

“预期”输出:

name: 'b', value1: 1, max(id): 2
Run Code Online (Sandbox Code Playgroud)

实际输出:

name: 'a', value1: 1, max(id): 2
Run Code Online (Sandbox Code Playgroud)