2010-11-08 29 views
6

Tôi đang cố gắng thể hiện một truy vấn SQL bằng cách sử dụng API Tiêu chuẩn của NHibernate, và tôi đang gặp khó khăn vì tôi đang nghĩ theo cách cơ sở dữ liệu trung tâm trong khi NHibernate là đối tượng làm trung tâm.Tôi làm cách nào để thể hiện việc tham gia vào một truy vấn phụ được nhóm bằng NHibernate?

SQL (hoạt động tuyệt vời):

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 

Về cơ bản, đây là một tự tham gia của một bảng chống lại một tập hợp con của chính nó. Tôi cho rằng tôi có thể thử biến sự tự tham gia thành một hạn chế:

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) 

Nhưng tôi không chắc chắn cách thể hiện bằng cách sử dụng NHibernate; Tôi đang chiến đấu với ProjectionList của DetachedCriteria và chỉ muốn chọn max(id) trong khi nhóm theo col1.

Cảm ơn rất nhiều vì đề xuất của bạn!

+2

Bạn có thực sự cần sử dụng Tiêu chí không? HQL có thể phù hợp hơn. –

+0

Thành thật mà nói, đối với các loại truy vấn này - hãy lưu trữ tóc của bạn và sử dụng HQL hoặc SQL thuần tuý (với CreateSqlQuery). – cbp

+0

Vì truy vấn phụ dẫn đến một tập hợp các vô hướng thay vì các thực thể được ánh xạ, tôi sẽ thể hiện sự tham gia trong HQL như thế nào? –

Trả lời

1

AFAIK bạn không thể tham gia vào các truy vấn con trong NHibernate nhưng bạn có thể sắp xếp lại truy vấn để sử dụng mệnh đề EXISTS hoặc IN để tái tạo cùng một chức năng.

Tôi nhận ra câu hỏi yêu cầu điều này được thực hiện bằng API tiêu chí nhưng tôi nghĩ tôi sẽ đăng phiên bản HQL có thể cung cấp cho người khác một số ý tưởng.

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

Tôi cũng tìm thấy vấn đề JIRA này xung quanh API tiêu chí và không bao gồm nhóm theo cột trong lựa chọn. Hiện tại, có vẻ như những gì bạn muốn không thể đạt được bằng cách sử dụng API tiêu chí.

Group By Property without adding it to the select clause

CẬP NHẬT Sử dụng ví dụ từ khỉ Coders bài vẻ như bạn có thể làm điều này:

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

nào sẽ tạo ra các SQL sau

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

Cảm ơn bạn đã nhảy vào. Những gì bạn đăng là bản dịch HQL tốt của phiên bản thứ hai của tôi (sử dụng IN), nhưng tôi tự hỏi HQL sẽ trông như thế nào đối với phiên bản JOIN. Bất kỳ suy nghĩ sâu sắc nào? –

+0

@David Rubin - Hiện tại NHibernate không hỗ trợ các loại tham gia đó (ví dụ: Tham gia vào các Truy vấn con trong HQL, Tiêu chí, Truy vấn hoặc LINQ). Mặc dù mệnh đề IN sẽ cung cấp cho bạn hầu như cùng một kế hoạch truy vấn. –

+0

@David Rubin - Với sự trợ giúp của MoneyCoder, tôi có phiên bản tiêu chí của truy vấn cho kết quả tương tự. –

6

I don' Tôi không biết tôi có nên đăng câu trả lời mới này hay thêm câu trả lời dưới dạng nhận xét về bài viết gốc estion, nhưng tôi nghĩ rằng tôi đã giải quyết được vấn đề tương tự trong chủ đề này:

Selecting on Sub Queries in NHibernate with Critieria API

+0

Làm tốt lắm. Một cách giải quyết hữu ích khác tôi có thể sử dụng bản thân mình. –

+0

được bình chọn để phân biệt với Mark Perry "The Xero Guy" – IamDeveloper

Các vấn đề liên quan