2010-11-08 5 views
6

Próbuję wyrazić kwerendę SQL przy użyciu interfejsu API NHibernate Criteria, a ja napotykam na trudności, ponieważ myślę w sposób zorientowany na bazę danych, podczas gdy NHibernate jest obiektowo zorientowany.Jak mogę wyrazić zgodę na dołączanie do podzapytania pogrupowanego za pomocą NHibernate?

SQL (działa świetnie):

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 

Zasadniczo, jest to samosprzężenie z tabeli przeciwko podgrupie sobie. Przypuszczam, że mógłbym spróbować obrócić samosprzężenie do ograniczenia:

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) 

Ale nie jestem pewien, jak to wyrazić, że za pomocą NHibernate albo; Walczę z ProjectionList DetachedCriteria i chcę wybrać tylko max(id) podczas grupowania przez col1.

Dziękuję bardzo za sugestie!

+2

Czy naprawdę trzeba użyć kryteria? HQL może być lepszym rozwiązaniem. –

+0

Szczerze mówiąc, w przypadku tego typu zapytań - zapisz włosy i używaj HQL lub po prostu starego SQL (z CreateSqlQuery). – cbp

+0

Ponieważ podzapytanie powoduje zbieranie skalarów zamiast zmapowanych jednostek, jak wyrazić sprzężenie w HQL? –

Odpowiedz

1

AFAIK, którego nie można dołączyć do podkwerend w ogóle w NHibernate, ale można ponownie zorganizować kwerendę, aby użyć klauzuli EXISTS lub IN do replikowania tej samej funkcjonalności.

Zdaję sobie sprawę, że pytanie wymaga tego przy pomocy API Criteria, ale pomyślałem, że opublikuję wersję HQL, która może dać komuś jakieś pomysły.

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

znalazłem też ten problem JIRA otaczającą API kryteria i nie włączając grupy kolumnami w select. Obecnie wygląda na to, że nie można osiągnąć tego za pomocą interfejsu API Criteria.

Group By Property without adding it to the select clause

UPDATE Korzystając z przykładu z Monkey Coders postu wygląda można to zrobić:

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

Który da następujący SQL

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

Dzięki za skakanie. To, co napisałeś, to dobre tłumaczenie HQL mojej drugiej wersji (używając IN), ale zastanawiam się, jak będzie wyglądać HQL dla wersji JOIN. Jakieś głębokie myśli? –

+0

@David Rubin - Obecnie NHibernate nie obsługuje tych typów połączeń (np. Dołącza się do subQueries w HQL, Criteria, QueryOver lub LINQ). Chociaż klauzula IN da ci prawie ten sam plan zapytania. –

+0

@David Rubin - Z pomocą MoneyCoder mam wersję kryteriów zapytania, która daje takie same wyniki. –

6

I don” t wiem, czy powinienem opublikować to jako nową odpowiedź lub dodać ją jako komentarz do oryginalnego qu estion, ale myślę, że już rozwiązany podobny problem w tym wątku:

Selecting on Sub Queries in NHibernate with Critieria API

+0

Dobra robota. Kolejne użyteczne obejście, z którego mogę skorzystać. –

+0

przegłosowano, aby odróżnić od Marka Perry'ego "The Xero Guy" – IamDeveloper

Powiązane problemy