quarta-feira, 29 de setembro de 2010

Group by

Tem uma coisa diferente nessa vida é o group by do sql.

Era uma vez duas entidades:

@Entity
public class Entidade1{
      @OneToMany
       private List<entidade2> lista;
}

@Entity
public class Entidade2{
       private String desc;
    
       @ManyToOne
       private Entidade1 entidade1;
       //outras coisas
}


Não carece de muita imaginação para perceber como ficavam essas duas tabelas, usando JoinColumn para o OneToMany. A pesquisa era: uma lista de 'Entidade1' a partir de um trecho de 'desc'.

A primeira tentativa era com groupBy. O grande problema ali é entender que o group by não retorna nada que não tenha sido agrupado, só podemos retornar o que está no group by ou funções agregadoras.

Então, o sql:
select e2.desc from Entidade2 e2 where e2.desc like '%algumaCoisa%' group by e2.id_entidade1
simplesmente não faz sentido e não funciona. 'Desc' é diferente para cada registro, como o BD vai adivinhar o que ele tem que retornar? Ele não vai concatenar tudo e jogar numa coluna só, não. Ele não vai pegar o primeiro, tem que ter garantias que é igual para todos os caras do grupo.

Por outro lado, uma opção seria (não, eu não gosto de usar join):
select * from Entidade1 e1, Entidade2 e2
where e2.entidade1_id = e1.id
and e1.id in
(
     select e3.entidade1_id from Entidade2 e3
     where e3.desc like '%algumaCoisa%'
) order by e1.id, e2.desc
O ponto é que isto retorna um registro para cada Entidade2 que existem na Entidade1 relacionadas, então na interface isso teria que ser tratado de alguma forma. Chato, mas às vezes necessário.
Importante notar que o SQL acima tem 'in' - o que tem sido bem lento na prática para mim - então seria bom tentar transformá-lo em um 'exists'.

Agora, já que estamos no hibernate e somos gente grande, não custa um HQL de gente:
select distinct e2.entidade1 where e2.desc like  '%algumaCoisa%'.

Se fosse Criteria, teria que fazer aquele DISTINCT ROOT para voltar só uma Entidade1 por grupo de Entidade2's.
 

Nenhum comentário:

Postar um comentário