-->
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.  [ 4 posts ] 
Author Message
 Post subject: How do I set/enforce a row limit in a subquery
PostPosted: Mon Sep 22, 2008 8:48 pm 
Newbie

Joined: Mon Sep 22, 2008 8:15 pm
Posts: 3
Hi - I am trying to build a fairly complex query to achieve the following;

I have set of reference tables that define a building structure (building, floor, area, item). I have a *register* which has events that are linked to the lowest level in the building structure - i.e. items. The linking table is RegisterItem and the event table is RegisterItemEvent

A single register can contain 1000's of buildings and therefore many 1000's of register items/events. I want to add a row limiter to my query, since it can take a long time to return for lots of data. However this limit needs to apply to the buildings and not the RegisterItemEvents, which is the object the query is returning.

So I have tried to build an *in* clause into the query whose subquery only returns a limited number of buildings - using the *top* statement. See below for the query. This query works fine in native SQL but it seems HQL doesn't support *top* unless used via the SetMaxResults() method in IQuery.

Is there anyway to achieve what I am after here in a single HQL query?

Code:
from RegisterItemEvent rie
where <WHERE CLAUSE>
and rie.RegisterItem.Item.Area.Floor.Building.Id in
(
select  distinct top 100 sub.RegisterItem.Item.Area.Floor.Building.Id
from  RegisterItemEvent   sub
where <WHERE_CLAUSE>
)


Any help will be warmly appreciated!


NHibernate version: 1.2.1.4000

Full stack trace of any exception that occurs:

NHibernate.QueryException was unhandled
Message="undefined alias or unknown mapping: top [select rie.LevelOfIdentification, rie.RegisterItem.Item.Area.Floor.Building.Id, rie.RegisterItem.Item.Area.Floor.Building.Name, rie.RegisterItem.Item.Area.Floor.Id, rie.RegisterItem.Item.Area.Floor.Name, rie.RegisterItem.Item.Area.Id, rie.RegisterItem.Item.Area.Name, rie.RegisterItem.Item.Id, rie.RegisterItem.Item.Name from ngNINE.Amianto.Client.Domain.RegisterItemEvent rie where rie.RegisterItem.Register.Id = :registerId and rie.RegisterItem.DeleteFl = false and rie.Dttm = (select max(inrrie.Dttm) from ngNINE.Amianto.Client.Domain.RegisterItemEvent inrrie where inrrie.RegisterItem.Id = rie.RegisterItem.Id and inrrie.Dttm <= :dttm) and rie.RegisterItem.Item.Area.Floor.Building.Id in ( select distinct top 100 sub.RegisterItem.Item.Area.Floor.Building.Id from ngNINE.Amianto.Client.Domain.RegisterItemEvent sub where sub.RegisterItem.Register.Id = :registerId and sub.RegisterItem.DeleteFl = false and sub.Dttm = (select max(inrsub.Dttm) from ngNINE.Amianto.Client.Domain.RegisterItemEvent inrsub where inrsub.RegisterItem.Id = sub.RegisterItem.Id and inrsub.Dttm <= :dttm) ) order by rie.RegisterItem.Item.Area.Floor.Building.Id, rie.RegisterItem.Item.Area.Floor.Id, rie.RegisterItem.Item.Area.Id ]"
Source="NHibernate"
QueryString="select rie.LevelOfIdentification, rie.RegisterItem.Item.Area.Floor.Building.Id, rie.RegisterItem.Item.Area.Floor.Building.Name, rie.RegisterItem.Item.Area.Floor.Id, rie.RegisterItem.Item.Area.Floor.Name, rie.RegisterItem.Item.Area.Id, rie.RegisterItem.Item.Area.Name, rie.RegisterItem.Item.Id, rie.RegisterItem.Item.Name from ngNINE.Amianto.Client.Domain.RegisterItemEvent rie where rie.RegisterItem.Register.Id = :registerId and rie.RegisterItem.DeleteFl = false and rie.Dttm = (select max(inrrie.Dttm) from ngNINE.Amianto.Client.Domain.RegisterItemEvent inrrie where inrrie.RegisterItem.Id = rie.RegisterItem.Id and inrrie.Dttm <= :dttm) and rie.RegisterItem.Item.Area.Floor.Building.Id in ( select distinct top 100 sub.RegisterItem.Item.Area.Floor.Building.Id from ngNINE.Amianto.Client.Domain.RegisterItemEvent sub where sub.RegisterItem.Register.Id = :registerId and sub.RegisterItem.DeleteFl = false and sub.Dttm = (select max(inrsub.Dttm) from ngNINE.Amianto.Client.Domain.RegisterItemEvent inrsub where inrsub.RegisterItem.Id = sub.RegisterItem.Id and inrsub.Dttm <= :dttm) ) order by rie.RegisterItem.Item.Area.Floor.Building.Id, rie.RegisterItem.Item.Area.Floor.Id, rie.RegisterItem.Item.Area.Id "
StackTrace:
at NHibernate.Hql.Classic.PathExpressionParser.Token(String token, QueryTranslator q)
at NHibernate.Hql.Classic.ParserHelper.Parse(IParser p, String text, String seperators, QueryTranslator q)
at NHibernate.Hql.Classic.SelectParser.Token(String token, QueryTranslator q)
at NHibernate.Hql.Classic.ClauseParser.Token(String token, QueryTranslator q)
at NHibernate.Hql.Classic.ClauseParser.End(QueryTranslator q)
at NHibernate.Hql.Classic.PreprocessingParser.End(QueryTranslator q)
at NHibernate.Hql.Classic.ParserHelper.Parse(IParser p, String text, String seperators, QueryTranslator q)
at NHibernate.Hql.Classic.QueryTranslator.Compile()
at NHibernate.Hql.Classic.QueryTranslator.Compile(QueryTranslator superquery)
at NHibernate.Hql.Classic.WhereParser.Token(String token, QueryTranslator q)
at NHibernate.Hql.Classic.ClauseParser.Token(String token, QueryTranslator q)
at NHibernate.Hql.Classic.PreprocessingParser.Token(String token, QueryTranslator q)
at NHibernate.Hql.Classic.ParserHelper.Parse(IParser p, String text, String seperators, QueryTranslator q)
at NHibernate.Hql.Classic.QueryTranslator.Compile()
at NHibernate.Hql.Classic.QueryTranslator.Compile(IDictionary replacements, Boolean scalar)
at NHibernate.Impl.SessionFactoryImpl.GetQuery(String queryString, Boolean shallow, IDictionary enabledFilters)
at NHibernate.Impl.SessionImpl.GetQueries(String query, Boolean scalar)
at NHibernate.Impl.SessionImpl.Find(String query, QueryParameters parameters, IList results)
at NHibernate.Impl.SessionImpl.Find(String query, QueryParameters parameters)
at NHibernate.Impl.QueryImpl.List()
at ngNINE.Common.Domain.SessionWrapper.ExecuteHQL(IQuery query) in d:\Amianto\Common\src\ngNINE\Common\Domain\SessionWrapper.cs:line 217
at ngNINE.Amianto.Client.Controls.RegisterUI.RegisterSearchUI.ExecuteSearch() in D:\Amianto\Amianto\src\ngNINE\Amianto\Client\Controls\RegisterUI\RegisterSearchUI.cs:line 606
at ngNINE.Amianto.Client.Controls.RegisterUI.RegisterSearchUI.btnSearch_Click(Object sender, EventArgs e) in D:\Amianto\Amianto\src\ngNINE\Amianto\Client\Controls\RegisterUI\RegisterSearchUI.cs:line 1027
at System.Windows.Forms.Control.OnClick(EventArgs e)
at Janus.Windows.EditControls.UIButton.OnClick(EventArgs e)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at ngNINE.Amianto.Client.Main.Program.Main() in D:\Amianto\Amianto\src\ngNINE\Amianto\Client\Main\Program.cs:line 34
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

Name and version of the database you are using:

Microsoft SQL Server 2005 - 9.00.3068.00 (Intel X86) Feb 26 2008 18:15:01 Copyright (c) 1988-2005 Microsoft Corporation Express Edition on Windows NT 5.1 (Build 2600: Service Pack 3)

Code:


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 22, 2008 9:43 pm 
Expert
Expert

Joined: Mon Nov 26, 2007 2:29 pm
Posts: 443
Criteria criteria=session.createCriteria(Item.class);
criteria.addOrder(Order.asc("name"));
criteria.setFirstResult(100);
criteria.setMaxResults(50);
List pageResults=criteria.list();

_________________
Gonzalo Díaz


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 22, 2008 11:31 pm 
Newbie

Joined: Mon Sep 22, 2008 8:15 pm
Posts: 3
Thanks Gonzalo - but I am not quite sure what you mean. I have had a look at the docs and tried a few things but can't seem to see how it should work.

I think the ICriteria might be able to help - I am just unsure how to use it in this case.

Here is the raw SQL query I am trying to replicate...

Code:
select *
from RegisterItemEvent   rie,
    RegisterItem      rgi,
    Item            itm,
    Area            ara,
    Floor            flr
where rie.RgiId = rgi.Id
and     itm.Id = rgi.ItmId
and     ara.Id = itm.AraId
and     flr.Id = ara.FlrId
and     rgi.RegId = 1
and   rgi.DeleteFl = 0
and   rie.RieDttm = (select max(inr.RieDttm)
                     from   RegisterItemEvent inr
                where  inr.RgiId = rie.RgiId
                and    inr.RieDttm <= getdate())
and     flr.BldId in (select distinct top 100 bld2.Id
               from Building         bld2,
                   RegisterItemEvent   rie2,
                   RegisterItem      rgi2,
                   Item            itm2,
                   Area            ara2,
                   Floor            flr2
               where rie2.RgiId = rgi2.Id
               and     itm2.Id = rgi2.ItmId
               and     ara2.Id = itm2.AraId
               and     flr2.Id = ara2.FlrId
               and     bld2.Id = flr2.BldId
               and     rgi2.RegId = 1
               and   rgi2.DeleteFl = 0
               and   rie2.RieDttm = (select max(inr2.RieDttm)
                               from   RegisterItemEvent inr2
                               where  inr2.RgiId = rie2.RgiId
                               and    inr2.RieDttm <= getdate())
               )


Note: I have hardcoded the RegId and Dttm parameters to 1 and getdate() respectively.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 25, 2008 6:24 pm 
Expert
Expert

Joined: Mon Nov 26, 2007 2:29 pm
Posts: 443
Well, that is a sizable query with several subselects on the same tables.
I recommend that you read the chapter on the documentation about Criteria queries

http://www.hibernate.org/hib_docs/refer ... teria.html

especially the sections dealing with alias and subqueries, and start experimenting with them, first without the self - joins, then with them.

You will have first to get the mapping files for the tables you use right.

Then you will find out that working with Criteria queries is quite comfortable, especially since it saves you from writing all that join information repeatedly in SQL queries.

But no answer I could discuss here replaces the fact that you have to get a good understanding of what Criteria are, at least by reading the indicated chapter.

Good luck.

_________________
Gonzalo Díaz


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 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.