Doctrine createQueryBuilder Group By

6 views
Skip to first unread message

Gustavo V. Goulart

unread,
Sep 5, 2018, 2:17:32 PM9/5/18
to zfbr...@googlegroups.com
Prezados boa tarde.

Estou precisando agrupar pela DATA_INICIO o resultado dessa consulta e
não estou conseguindo. Alguem consegue ajudar?

       $em = $this->getEntityManager();
      
        $qb = $em->createQueryBuilder();

        $qb->select('u');
        $qb->from('Servico\Model\Servico', 'u');
        
        $qb->where('u.STATUS IN (:status)');
        $qb->setParameter('status', ['2', '3', '4', '6']);

        if ($cliente) {
            $qb->andWhere('u.CLIENTE = :cliente');
            $qb->setParameter('cliente', $cliente);
        }

        if ($fornecedor) {
            $qb->andWhere('u.FORNECEDOR = :fornecedor');
            $qb->setParameter('fornecedor', $fornecedor);
        }

        if ($motorista) {
            $qb->andWhere('u.MOTORISTA = :motorista');
            $qb->setParameter('motorista', $motorista);
        }

        if ($fileCliente) {
            $qb->andWhere('u.FILE = :file_cliente');
            $qb->setParameter('file_cliente', $fileCliente);
        }

        if ($inicio AND $fim) {
            $qb->andWhere('u.DATA_INICIO BETWEEN :inicio AND :fim');
            $qb->setParameter('inicio', $inicio);
            $qb->setParameter('fim', $fim);
        }

        $qb->orderBy('u.DATA_INICIO', 'ASC');
        $qb->addOrderBy('u.HORA_INICIO', 'ASC');
        //$qb->groupBy('u.DATA_INICIO');    ---> Isso não funciona

        $query = $qb->getQuery();

        return $query->getResult();

Rafael Rocha

unread,
Sep 5, 2018, 5:07:57 PM9/5/18
to zfbr...@googlegroups.com
Gustavo,
Seu sql está errado. Você precisa de uma função agregadora(sum, count, avg, etc) com o campo para agregar.

Você está fazendo select * from servico group by data => isso não dá certo
O correto seria select data, count(item) from servico group by data

Tente rodar o sql direto no banco para ver a crítica

--
Essa mensagem faz parte do grupo "zfbrasil" no Google Groups.
Para escrever neste grupo, envie um email para zfbr...@googlegroups.com
Para se desligar do grupo, envie um email para zfbrasil-u...@googlegroups.com
Mais informações, visite o grupo em http://groups.google.com/group/zfbrasil?hl=pt-BR
---
Você está recebendo esta mensagem porque se inscreveu no grupo "Zend Framework Brasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para zfbrasil+u...@googlegroups.com.
Para obter mais opções, acesse https://groups.google.com/d/optout.


--

Marcelo Bento

unread,
Sep 6, 2018, 1:46:35 PM9/6/18
to Zend Group
Bom, você pode até usar o group by sem função de agregação! No seu caso como você está fazendo um $qb->select('u') ele faz um select *
ai você teria que colocar todas as colunas da sua tabela no group by.

Tente fazer um ->select('u.dataInicio, u.status')->groubBy('u.dataInicio, u.status')

Você recebeu essa mensagem porque está inscrito no grupo "Zend Framework Brasil" dos Grupos do Google.

Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para zfbrasil+u...@googlegroups.com.
Para mais opções, acesse https://groups.google.com/d/optout.

gvil...@gmail.com

unread,
Sep 6, 2018, 9:42:04 PM9/6/18
to zfbr...@googlegroups.com
Cara, ja tentei assim:

        $qb = $em->createQueryBuilder();

        $qb->select('u.DATA_INICIO, count(u.IDSERVICO)');
       
Assim:

  $qb->select('u.DATA_INICIO');
        $qb->from('Servico\Model\Servico', 'u');
         ....


        $qb->orderBy('u.DATA_INICIO', 'ASC');
        $qb->addOrderBy('u.HORA_INICIO', 'ASC');
        $qb->groupBy('u.DATA_INICIO');

        $query = $qb->getQuery();
//        $em->clear();
        return $query->getResult();

Não funciona ... A query nem é executada, sei pq fico olhando os logs do MySQL....

Marcelo Bento

unread,
Sep 10, 2018, 10:04:15 AM9/10/18
to Zend Group
Apresenta algum erro na execução?

Estranho não funcionar dessa forma!



Você recebeu essa mensagem porque está inscrito no grupo "Zend Framework Brasil" dos Grupos do Google.

Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para zfbrasil+u...@googlegroups.com.
Para mais opções, acesse https://groups.google.com/d/optout.

gvil...@gmail.com

unread,
Sep 10, 2018, 11:10:13 AM9/10/18
to zfbr...@googlegroups.com
Opá Marcelo,

Não aparece nada... Apesar que vc me lembrou de habilitar o display no php, vou fazer isso e te falo. No log do MySQL não aparece nada, ele nem executa.

gvil...@gmail.com

unread,
Sep 10, 2018, 12:58:29 PM9/10/18
to zfbr...@googlegroups.com
Fala Marcelo. Cara, realmente não aparece nenhum erro, habilitei o display_erro no php.ini e não aperece nada.

Então, acho que pelo código já deu para perceber o que faço com essa função. É um filtro que monta a query dependendo do que o usuário preencher, DATA_INICIO e FIM, são obrigatórios, se ele selecionar CLIENTE eu filtro por inicio, fim e cliente e assim por diante. Coloco a função inteira abaixo. Vc indica alguma maneira melhor de fazer isso? Alguma forma que o GROUP BY funcione?
Essa tabela tem vários campos e alguns relacionamentos, preciso mostrar város desses campos na view, acho que é por isso que quando coloco u.DATA_INICO não esta funcionando. Já tentei

u, u.DATA_INICIO, count(u.IDSERVICO)

Ja tentei tbm

$em->createQueryBuilder('u');

Eu preciso do select * ,

public function periodo($cliente = false, $fornecedor = false, $motorista = false, $fileCliente = false, $inicio = false, $fim = false) {

        $em = $this->getEntityManager();

        $qb = $em->createQueryBuilder();

        $qb->select('u.DATA_INICIO, count(u.IDSERVICO)');
       
        $qb->from('Servico\Model\Servico', 'u');
        
        $qb->where('u.STATUS IN (:status)');
        $qb->setParameter('status', ['2', '3', '4', '6']);

        if ($cliente) {
            $qb->andWhere('u.CLIENTE = :cliente');
            $qb->setParameter('cliente', $cliente);
        }

        if ($fornecedor) {
            $qb->andWhere('u.FORNECEDOR = :fornecedor');
            $qb->setParameter('fornecedor', $fornecedor);
        }

        if ($motorista) {
            $qb->andWhere('u.MOTORISTA = :motorista');
            $qb->setParameter('motorista', $motorista);
        }

        if ($fileCliente) {
            $qb->andWhere('u.FILE = :file_cliente');
            $qb->setParameter('file_cliente', $fileCliente);
        }

        if ($inicio AND $fim) {
            $qb->andWhere('u.DATA_INICIO BETWEEN :inicio AND :fim');
            $qb->setParameter('inicio', $inicio);
            $qb->setParameter('fim', $fim);
        }

        $qb->orderBy('u.DATA_INICIO', 'ASC');
        $qb->addOrderBy('u.HORA_INICIO', 'ASC');
        $qb->groupBy('u.DATA_INICIO');

        $query = $qb->getQuery();

        return $query->getResult();
    }

Marcelo Bento

unread,
Sep 10, 2018, 2:58:57 PM9/10/18
to Zend Group
Faz um pequeno teste.
Ao invés de retornar o getResult retorna o getArrayResult


gvil...@gmail.com

unread,
Sep 10, 2018, 3:59:24 PM9/10/18
to zfbr...@googlegroups.com
Não foi, não funcionou.
Cara, eu tenho uns relatórios no qual uso SQL nativo mesmo, com join e devolvo um array ao inveis de objeto. Já estou pensando em fazer isso aqui tbm, minha dificuldade é colocar esses "IFs" no meio.
Indica alguma coisa?
Esse é um exemplo ... Como vou montar a query aqui dependendo da seleção do usuario?

$em = $this->getEntityManager();

        $sql = "SELECT
                     SUM(SERVICO.QUANT_CARRO) AS QUANTIDADE,
                     SUM(SERVICO.VALOR_FOR) AS VALOR_FOR,
                     SUM(SERVICO.VALOR_ACRESCIMO) AS VALOR_ACRESCIMO,
                     SUM(SERVICO.VALOR) AS VALOR,
                     SUM(SERVICO.VALOR + SERVICO.VALOR_ACRESCIMO)-SUM(SERVICO.VALOR_FOR) AS TOTAL,
                     TIPO_CARRO.DESCRICAO AS VEICULO

                FROM
                     TARIFARIO TARIFARIO INNER JOIN SERVICO SERVICO ON TARIFARIO.IDTARIF = SERVICO.ID_TARIF
                     INNER JOIN TIPO_CARRO TIPO_CARRO ON TARIFARIO.ID_TIPO_CARRO = TIPO_CARRO.ID_TIPO_CARRO
                     INNER JOIN PESSOA PESSOA ON PESSOA.IDPESSOA = SERVICO.CLIENTE
                WHERE
                      SERVICO.STATUS <> 5 AND SERVICO.DATA_INICIO BETWEEN :pid1 AND :pid2 AND PESSOA.IDPESSOA = :pid3

                GROUP BY TIPO_CARRO.DESCRICAO";

        $stmt = $em->getConnection()->prepare($sql);
        $stmt->bindParam("pid1", $inicio);
        $stmt->bindParam("pid2", $fim);
        $stmt->bindParam("pid3", $cli);
        $stmt->execute();
        return $stmt->fetchAll();

gvil...@gmail.com

unread,
Sep 10, 2018, 8:49:43 PM9/10/18
to zfbr...@googlegroups.com
Opá Marcelo, boa noite.

Cara, da maneira que eu queria colocar para funcionar, não ia funcionar nunca. Fui executar a query direto no MySQL e tive o seguinte erro:
of SELECT list is not in GROUP BY clause and contains nonaggregated column 'SIT.SERVICO.HORA_INICIO' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
Ou seja, se eu quero fazer um SELECT *, DATA_INICIO, count(*) FROM .... Eu teria que usar uma função agregada para cada coluna da tabela.

**** TRADUÇÃO GOOGLE *****
Ao selecionar uma coluna que não faz parte do GROUP BY, pode haver vários valores para essa coluna nos grupos, mas haverá apenas espaço para um único valor nos resultados. Portanto, o banco de dados geralmente precisa ser informado exatamente como transformar esses valores múltiplos em um valor. Geralmente, isso é feito com uma função agregada como COUNT (), SUM (), MAX () etc ... Eu digo normalmente porque a maioria dos outros sistemas de banco de dados populares insistem nisso. No entanto, no MySQL anterior à versão 5.7, o comportamento padrão foi mais indulgente, porque ele não irá reclamar e, então, escolher arbitrariamente qualquer valor! Ele também tem uma função ANY_VALUE () que poderia ser usada como outra solução para essa pergunta se você realmente precisasse do mesmo comportamento de antes. Essa flexibilidade tem um custo porque não é determinista, então eu não a recomendaria a menos que você tenha uma boa razão para precisar dela. O MySQL agora está ativando a configuração only_full_group_by por padrão por boas razões, então é melhor se acostumar com isso e fazer com que suas consultas estejam de acordo com isso.

**********************************

Minha consulta nunca iria funcionar. Obrigado pela Ajuda.


Em seg, 2018-09-10 às 11:04 -0300, Marcelo Bento escreveu:

Marcelo Bento

unread,
Sep 17, 2018, 1:50:31 PM9/17/18
to Zend Group
Isso aconteceu porque você fez um select *. Desta forma você vai ter que colocar todos os campos no group by.

Você recebeu essa mensagem porque está inscrito no grupo "Zend Framework Brasil" dos Grupos do Google.

Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para zfbrasil+u...@googlegroups.com.
Para mais opções, acesse https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages