2010-11-08 5 views
6

Sto cercando di esprimere una query SQL utilizzando l'API Criteria di NHibernate e sto riscontrando delle difficoltà perché sto pensando in un modo centrato sul database mentre NHibernate è object-centric.Come posso esprimere l'adesione a una sottoquery raggruppata utilizzando NHibernate?

SQL (grandi opere):

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 

In sostanza, si tratta di un self-join di un tavolo contro un sottoinsieme di se stesso. Suppongo che avrei potuto provare a girare il self-join in una restrizione:

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) 

Ma io non sono sicuro di come esprimere che l'uso di NHibernate sia; Sto combattendo con ProjectionList di DetachedCriteria e voglio selezionare solo max(id) mentre raggruppo per col1.

Grazie mille per i vostri suggerimenti!

+2

non si ha realmente bisogno di utilizzare criteri? HQL potrebbe essere una soluzione migliore. –

+0

Onestamente, per questi tipi di query - salva i tuoi capelli e usa HQL o semplicemente SQL vecchio (con CreateSqlQuery). – cbp

+0

Poiché la sottoquery risulta in una raccolta di scalari anziché entità mappate, come potrei esprimere il join in HQL? –

risposta

1

AFAIK non è possibile unirsi a subquery in tutto in NHibernate ma è possibile riorganizzare la query per utilizzare una clausola EXISTS o IN per replicare la stessa funzionalità.

Mi rendo conto che la domanda richiede che ciò avvenga utilizzando l'API Criteria ma ho pensato di pubblicare una versione HQL che potrebbe dare a qualcun altro alcune idee.

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

Ho trovato anche questo problema JIRA circonda l'API Criteria e non compreso gruppo dalle colonne selezionate. Attualmente sembra che non si possa ottenere ciò che si desidera utilizzando l'API Criteria.

Group By Property without adding it to the select clause

UPDATE Utilizzando l'esempio da Monkey codificatori posta Sembra che si può fare questo:

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)); 

che produrrebbe il seguente SQL

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

Grazie per il salto. Quello che hai postato è una buona traduzione HQL della mia seconda versione (usando IN), ma mi chiedo come sarà l'HQL per la versione JOIN. Qualche pensiero profondo? –

+0

@David Rubin: attualmente NHibernate non supporta questi tipi di join (ad esempio join a sottoscatori in HQL, Criteria, QueryOver o LINQ). Sebbene la clausola IN fornirà quasi lo stesso piano di query. –

+0

@David Rubin - Con l'aiuto di MoneyCoder ho una versione dei criteri della query che fornisce gli stessi risultati. –

6

I don' so se dovrei postare questa come una nuova risposta o aggiungerla come un commento sulla qu originale estion, ma credo di aver risolto un problema simile in questa discussione:

Selecting on Sub Queries in NHibernate with Critieria API

+0

Bel lavoro. Un'altra soluzione utile che posso usare da solo. –

+0

ingrandito per distinguere da Mark Perry "The Xero Guy" – IamDeveloper