-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 14 posts ] 
Author Message
 Post subject: Howto Join with subquery using Critieria api?
PostPosted: Sat Jul 26, 2008 4:33 am 
Newbie

Joined: Sat Apr 05, 2008 6:33 pm
Posts: 16
Hi,

I have this entity: ChangeItem { Id, Path, Revision }

I would like to do this sql query:

select * from ChangeItems c1
inner join (
select Path, Max(Revision) as Revision from ChangeItems c2
Group by Path
) c2 on c1.Path=c2.Path and c1.Revision=c2.Revision

Basically select all ChangeItems of the highest revision for a path.

To define the inner query was no problem:

var innerQuery = DetachedCriteria.For<ChangeItem>("c2")
.SetProjection(Projections.ProjectionList()
.Add(Projections.Property("Path"))
.Add(Projections.Max("Revision"))
.Add(Projections.GroupProperty("Path")))

But how to a define a new critiera and then join that with the innerQuery? I have been googling and browseing through the nhibernate source and test cases and I am a little unsure if it is possible.

I was hoping do do something like this:

var items = DetachedCriteria.For<ChangeItem>("c1")
.CreateCriteria(innerQuery)
.Add(Property.ForName("Path).EqProperty("c2.Path")
.Add(Property.ForName("Revision).EqProperty("c2.Revision")

Anyone know if it is possible in nhibernate to join to subquery? To me it looks like it has to be a association.

/Torkel


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 29, 2008 8:02 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
You can try this:

Code:
ICriteria subquery = DetachedCriteria.For<ChangeItem>("c2")
    .Add(Expression.EqProperty("c1.Path", "c2.Path")
    .SetProjection(Projection.Max("Revision"));

var items = session.CreateCriteria(typeof(ChangeItem), "c1")
    .Add(Subqueries.PropertyEq("c1.Revision", subquery)
    .List();

_________________
--Wolfgang


Top
 Profile  
 
 Post subject:
PostPosted: Sat Aug 02, 2008 11:42 am 
Newbie

Joined: Sat Apr 05, 2008 6:33 pm
Posts: 16
Thanks for the replay, I do not think that will result in the same thing though, but I will try it.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Aug 02, 2008 12:27 pm 
Newbie

Joined: Sat Apr 05, 2008 6:33 pm
Posts: 16
Nope :(

That query does not return the correct result :(

I guess I have to use a native SQL Query for this one. But I am having trouble getting it to work, it seams like you can not use CreateSQLQuery for entities that contain formula properties. Even when you include the formula and name it exactly like the one generated by NHibernate.

You get a expection:

System.ArgumentNullException: Value cannot be null.
Parameter name: fieldName
at System.Data.ProviderBase.FieldNameLookup.GetOrdinal(String fieldName)

It seems like the loading is passing in null for the formula property, this problem has been reported in this thread: http://forum.hibernate.org/viewtopic.php?p=2374703


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 04, 2008 3:26 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
Quote:
Basically select all ChangeItems of the highest revision for a path.


That's what the criteria I posted should do.

Quote:
Thanks for the replay, I do not think that will result in the same thing though, but I will try it.


What's the difference between the result the criteria has and what you need ?

_________________
--Wolfgang


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 04, 2008 5:51 am 
Newbie

Joined: Sat Apr 05, 2008 6:33 pm
Posts: 16
For the subquery I need to group by path, and it does not seem to be possible to do a group by without projecting the grouped by property. So if I add a Group By projection and the Max(Revision) projection I can no longer use the Subqueries.PropertyEq method as the subquery returns more than one value.

Example of data:
Rev Path
1 /trunk/file.txt
2 /trunk/file.txt

I want to fetch the rows with the latest revision, for a specific path. In theory it would work with SubQueries.EqProperty

for example this sql query works:
select * from ChangeItems c1 where c1.Revision = (select Max(Revision) from ChangeItems c2 where c1.Path=c2.Path group by Path)

But I don't know how to do this query with nhibernate as a group by will add the grouped by property to the projection list.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 04, 2008 5:54 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
Quote:
select * from ChangeItems c1 where c1.Revision = (select Max(Revision) from ChangeItems c2 where c1.Path=c2.Path group by Path)


I can't see why you need the group by ? With "c1.Path=c2.Path" you restrict the result set to a single path and there's no reason for grouping then.

_________________
--Wolfgang


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 04, 2008 8:32 am 
Newbie

Joined: Sat Apr 05, 2008 6:33 pm
Posts: 16
Sorry, I guess I simplified the scenario a little to much :)

I actually have this data:
Rev Path BasePath

I need to fetch all the latest (revisions) for a specific BasePath, so I need to group by path. Sorry for not including this important detail!


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 04, 2008 9:18 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
Hmmm .... I see. You can try this, but I'm not sure if it works.

Code:
ICriteria subquery = DetachedCriteria.For<ChangeItem>("c2")
    .Add(Expression.EqProperty("c1.BasePath", "c2.BasePath")
    .SetProjection(Projection.ProjectionList()
                .Add(Projection.Max("Revision"), "Revision")
                .Add(Projection.GroupProperty("Path"), "Path");

var items = session.CreateCriteria(typeof(ChangeItem), "c1")
    .Add(Subqueries.PropertyEq("c1.Revision",
             subquery.SetProjection(Projections.Property("Revision"))
    .List();

_________________
--Wolfgang


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 04, 2008 9:36 am 
Newbie

Joined: Sat Apr 05, 2008 6:33 pm
Posts: 16
You get a SqlException:

"Subquery returned more than 1 value"

Thanks for you help, I think I will take this up on the nh dev mailing list, see if there is change to either add the possibility to join to a subquery or do a group by without including the grouped by column in the select clause.

I think both these features should be good to have and at least the second one should not be to difficult to implement.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 04, 2008 9:57 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
Quote:
"Subquery returned more than 1 value"


Subqueries.PropertyEq isn't working anymore, since now there can be more then one row in the resultset of the query. It has to be Subqueries.PropertyIn ...

_________________
--Wolfgang


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 04, 2008 10:14 am 
Newbie

Joined: Sat Apr 05, 2008 6:33 pm
Posts: 16
Since the subquery selects MAX(Revision) and Path I do not think an IN clause will work.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 04, 2008 10:18 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
I hoped that

var items = session.CreateCriteria(typeof(ChangeItem), "c1")
.Add(Subqueries.PropertyEq("c1.Revision", subquery.SetProjection(Projections.Property("Revision"))
.List();

would have solved that ... but open a JIRA issue anyway, I agree with you, that grouping without projecting the property would be quite helpful.

_________________
--Wolfgang


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 04, 2008 10:41 am 
Newbie

Joined: Sat Apr 05, 2008 6:33 pm
Posts: 16
Yea, I hoped that too :)

I will open up a JIRA, and maybe have a look at doing a patch myself if I get the time.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 14 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.