2010-11-08 10 views
6

Estoy tratando de expresar una consulta SQL utilizando la API de Criterios de NHibernate, y estoy teniendo dificultades porque estoy pensando en una forma centrada en la base de datos, mientras que NHibernate está centrado en el objeto.¿Cómo puedo expresar la unión a una subconsulta agrupada utilizando NHibernate?

SQL (funciona muy bien):

select outerT.id, outerT.col1, outerT.col2, outerT.col3 
from tbl outerT 
inner join 
    (select max(innerT.id) 
    from tbl innerT 
    group by innerT.col1) grpT 
on outerT.id = grpT.id 

En esencia, se trata de una autocombinación de una mesa contra un subconjunto de sí mismo. Supongo que podría intentar girar el auto-ensambla en una restricción:

select outerT.id, outerT.col1, outerT.col2, outerT.col3 
from tbl outerT 
where outerT.id in (select max(innerT.id) from tbl innerT group by innerT.col1) 

Pero no estoy seguro de cómo expresar que el uso de NHibernate tampoco; Estoy peleando con ProjectionList de DetachedCriteria y quiero seleccionar solo max(id) al agrupar por col1.

¡Muchas gracias por sus sugerencias!

+2

lo que realmente necesita utilizar criterios? HQL podría ser un mejor ajuste. –

+0

Honestamente, para este tipo de consultas, guárdese y use HQL o simplemente SQL antiguo (con CreateSqlQuery). – cbp

+0

Dado que la subconsulta da como resultado una colección de escalares en lugar de entidades mapeadas, ¿cómo expresaría la unión en HQL? –

Respuesta

1

AFAIK no puede unirse a subconsultas en absoluto en NHibernate pero puede reorganizar la consulta para usar una cláusula EXISTS o IN para replicar la misma funcionalidad.

Me doy cuenta de que la pregunta requiere que esto se haga usando la API de Criteria, pero pensé que podría publicar una versión de HQL que puede darle a alguien más algunas ideas.

var results = session.CreateQuery("from Product p where p.Id in (
    select max(p2.id) 
from Product p2 
group by p2.col1 
)") 

También encontré este problema JIRA que rodea la API Criteria y no incluyendo el grupo de columnas en la selección. Actualmente, parece que lo que desea no se puede lograr utilizando la API de Criteria en absoluto.

Group By Property without adding it to the select clause

ACTUALIZACIÓN Usando el ejemplo del mono codificadores posterior parece que se puede hacer esto:

var subquery = DetachedCriteria.For<Product>("p") 
.SetProjection(Projections.ProjectionList() 
    .Add(Projections.GroupProperty("p.Col1")) 
.Add(Restrictions.EqProperty("p2.Id", Projections.Max("p.Id")); 

var query = DetachedCriteria.For<Product>("p2") 
.Add(Subqueries.Exists(subquery)); 

que produciría el siguiente código SQL

select * 
from Product p2 
where exists (
    select p.col1 
    from Product p 
    group by p.col1 
    having p2.Id=max(p.Id) 
) 
+0

Gracias por saltar. Lo que publicaste es una buena traducción de HQL de mi segunda versión (usando IN), pero me pregunto cómo sería el HQL para la versión JOIN. ¿Alguna idea profunda? –

+0

@David Rubin: actualmente NHibernate no es compatible con esos tipos de uniones (por ejemplo, se une a SubQuery en HQL, Criteria, QueryOver o LINQ). Aunque la cláusula IN le dará casi el mismo plan de consulta. –

+0

@David Rubin - Con la ayuda de MoneyCoder tengo una versión de criterio de su consulta que da los mismos resultados. –

Cuestiones relacionadas