Nesse post quero mostrar a você um truque de como usar ORDER BY antes de GROUP BY no MySQL – Como mudar a ordem no agrupamento.
Sabe aqueles coisas que fazem a gente quebrar a cabeça, toma um tempo de pesquisa, monte de testes e parece que nada funciona.
Geralmente, a gente acaba resolvendo essas coisas de uma forma simples, e as vezes até óbvia.
Então, olha a situação que passei aqui com um projeto de um cliente que é um sistema integrado com o WordPress.
Eles tem uma tabela de faturas e eu tinha os seguintes dados:
id | data_vencimento | tipo | subtipo | obs | metodo | id_gateway | id_gateway_carne |
---|---|---|---|---|---|---|---|
613 | 2021-10-01 | assinaturas | adesao | Assinatura do Plano PLANO ESSENCIAL | boleto | pay_7895303835179531 | |
629 | 2022-09-28 | assinaturas | mensalidade | Parcela 12 de 12. | carne | pay_7981416104016304 | ins_000004302035 |
630 | 2022-08-28 | assinaturas | mensalidade | Parcela 11 de 12. | carne | pay_0081214048722265 | ins_000004302035 |
631 | 2022-07-28 | assinaturas | mensalidade | Parcela 10 de 12. | carne | pay_9122622527213622 | ins_000004302035 |
632 | 2022-06-28 | assinaturas | mensalidade | Parcela 9 de 12. | carne | pay_8623810229282099 | ins_000004302035 |
633 | 2022-05-28 | assinaturas | mensalidade | Parcela 8 de 12. | carne | pay_0674774703026293 | ins_000004302035 |
634 | 2022-04-28 | assinaturas | mensalidade | Parcela 7 de 12. | carne | pay_7611885051824003 | ins_000004302035 |
635 | 2022-03-28 | assinaturas | mensalidade | Parcela 6 de 12. | carne | pay_5293743028322577 | ins_000004302035 |
636 | 2022-02-28 | assinaturas | mensalidade | Parcela 5 de 12. | carne | pay_4106004508788312 | ins_000004302035 |
637 | 2022-01-28 | assinaturas | mensalidade | Parcela 4 de 12. | carne | pay_7609326364902656 | ins_000004302035 |
638 | 2021-12-28 | assinaturas | mensalidade | Parcela 3 de 12. | carne | pay_6414323469614363 | ins_000004302035 |
639 | 2021-11-28 | assinaturas | mensalidade | Parcela 2 de 12. | carne | pay_0540964003353301 | ins_000004302035 |
640 | 2021-10-28 | assinaturas | mensalidade | Parcela 1 de 12. | carne | pay_0196847040996473 | ins_000004302035 |
Eu criei então uma rotina onde o usuário se cadastra e faz a assinatura de um dos planos e isso gera um boleto de adesão.
Em seguida, quando esse usuário/cliente paga essa fatura, recebo uma notificação via webhook (api) do gateway e o sistema então gerar um carnê de 12 parcelas.
Contudo, meu cliente solicitou que não fossem mostradas as 12 faturas do carnê, mas apenas a primeira parcela subsequente à adesão.
O usuário poderia depois ter um link para visualizar as demais faturas se quisesse.
Desse modo, tivemos que fazer o agrupamento usando o único campo que poderia ser usada nesse caso, o id_gateway_carne
.
Ficou assim no sistema:
Entretanto, você vai reparar que na listagem funcionou o agrupamento, mas contrariamente, ele mostrava sempre a última parcela do carnê.
Então, como usar ORDER BY antes de GROUP BY?
Bem, você deve saber que o ORDER BY vem depois do GROUP BY em uma query com essas cláusulas, certo?
E é por isso que nos resultados sempre mostrava assim, quando a gente rodava a seguinte query:
SELECT * FROM prfx_faturas WHERE tipo = 'assinaturas' AND id_auxiliar = 123 GROUP BY id_gateway_carne
Adicionar um ORDER BY ali no final da consulta não interferia em nada em relação ao objetivo que tínhamos.
Então, depois de umas pesquisas começamos a chegar em uma solução – veja essa query e o resultado a seguir:
SELECT MAX(id) MaxID, id, data_vencimento, tipo, subtipo, obs, metodo, id_gateway, id_gateway_carne
FROM prfx_faturas
WHERE id_auxiliar = 123
GROUP BY id_gateway_carne
O resultado:
MaxID | id | data_vencimento | tipo | subtipo | obs | metodo | id_gateway | id_gateway_carne |
---|---|---|---|---|---|---|---|---|
613 | 613 | 2021-10-01 | assinaturas | adesao | Assinatura do Plano PLANO ESSENCIAL | boleto | pay_7895303835179531 | |
640 | 629 | 2022-09-28 | assinaturas | mensalidade | Parcela 12 de 12. | carne | pay_7981416104016304 | ins_000004302035 |
Perceba que o id
do agrupamento das faturas e a data_vencimento
eram realmente da última parcela, mas usamos a função MAX
para pegar o id
máximo no caso.
Em alguns casos, você pode querer usar a função min
ou uma outra para obter algum valor que possa ser usado como referência para a ordenação.
Enfim…
Agora, tendo esse id
posso colocar essa consulta dentro de outra para chegar no resultado que eu gostaria.
Então, fiz da seguinte forma:
SELECT p1.id, p1.data_vencimento, p1.tipo, p1.subtipo, p1.obs, p1.metodo, p1.id_gateway, p1.id_gateway_carne
FROM prfx_faturas p1
INNER JOIN
(
SELECT MAX(id) MaxID
FROM prfx_faturas
WHERE id_auxiliar = 123
GROUP BY id_gateway_carne
) p2
ON p1.id = p2.MaxID
order by p1.id ASC
E o resultado foi:
id | data_vencimento | tipo | subtipo | obs | metodo | id_gateway | id_gateway_carne |
---|---|---|---|---|---|---|---|
613 | 2021-10-01 | assinaturas | adesao | Assinatura do Plano PLANO ESSENCIAL | boleto | pay_7895303835179531 | |
640 | 2021-10-28 | assinaturas | mensalidade | Parcela 1 de 12. | carne | pay_0196847040996473 | ins_000004302035 |
Então, conseguimos mostrar certinho, como o cliente solicitou.
Ah… E como estamos usando o WordPress, rodamos esse SQL usando $wpdb->get_results($sql)
.
Espero que isso ajude você aí…
Nos vemos no próximo post!
Grande abraço,