Nhibernate 3.0 IQueryOver分组并在满足条件的每个组中提取一条完整记录

时间:2019-01-31 12:18:44

标签: c# linq nhibernate queryover

我的要求是获取SiteItemOnHand记录,按Businessunitid,inventoryitemid分组,并获取每个具有max(lastmodifiedtimestamp)的组中的整个SiteItemOnHand记录

我正在尝试为以下SQL查询编写nhibernate等效查询

Select x.* from 
(
Select  businessunitid,inventoryitemid,max(lastmodifiedtimestamp) as maxvalue from InventoryItemBUOnHand  
group by businessunitid,inventoryitemid HAVING inventoryitemid in (939) and businessunitid=829
) as x
inner join
(
    Select  businessunitid,inventoryitemid,lastmodifiedtimestamp,inventoryitemonhandid from InventoryItemBUOnHand 
    where inventoryitemid in (939) and businessunitid=829
) as y
on x.businessunitid=y.businessunitid and  x.inventoryitemid =y.inventoryitemid and x.maxvalue=y.lastmodifiedtimestamp

我有很多限制。我只允许使用Nhibernate 3.0版本,并且严格禁止编写sql查询(条件)。 我只能写下面的查询的一半。任何帮助,将不胜感激。


var query= _session.QueryOver<SiteItemOnHand>()
      .Where(x => x.Businessunitid == siteID)
      .Where(x => x.End == endDate)
      .Where(x => x.CountID != filterCount.ID)
      .WhereRestrictionOn(x => x.ItemID).IsIn(itemIdList.ToArray())
      .SelectList(list => list
      .SelectMax(x => x.LastModifiedTimestamp)
      .SelectGroup(x => x.Businessunitid)
      .SelectGroup(x => x.ItemId));

上面的查询正在生成下面的SQL查询,该查询仅返回三列,但是我需要整个记录,因为检索记录后我需要更新。我需要获取满足上述查询的所有SiteItemOnHand记录。

SELECT max(this_.lastmodifiedtimestamp) as y0_, this_.businessunitid as y1_, this_.inventoryitemid as y2_ 
FROM InventoryItemBUOnHand this_ 
WHERE this_.businessunitid = 567 and this_.enddate = '1/31/2019 1:18:17 AM' and not (this_.itemcountid = 958) 
and this_.inventoryitemid in (744,755)
GROUP BY this_.businessunitid, this_.inventoryitemid

任何帮助将不胜感激。如果需要更多信息,请告诉我。

1 个答案:

答案 0 :(得分:0)

如果我对您的理解正确,那么您就有类似的数据,并且需要标记的记录。我不知道iventoryitemonhandid是否是表的id,所以我不依赖它。

Table InventoryItemBUOnHand (mapped as SiteItemOnHand)

| businessunitid|inventoryitemid|lastmodifiedtimestamp|inventoryitemonhandid|
|            829|            939|  2019-01-01 00:00:00|                  100| <--
|            829|            940|  2019-01-02 00:00:00|                  101| 
|            829|            940|  2019-01-03 00:00:00|                  102| <-- 
|            829|            950|  2019-01-04 00:00:00|                  103| 
|            829|            950|  2019-01-10 00:00:00|                  104| <--
|            829|            950|  2019-01-06 00:00:00|                  105|

如果是,那么我将使用类似于此问题的SubQuery: SO: NHibernate - Select full records from aggregates

根据您的要求进行了修改(未经测试),看起来像这样:

int siteID = 829;
List<int> itemIdList = new List<int>() { 939, 940, 950 };
SiteItemOnHand siAlias = null;

var subQuery = QueryOver.Of<SiteItemOnHand>()
    .Where(x => x.Businessunitid == siAlias.Businessunitid)
    .And(x => x.ItemID == siAlias.ItemID)
    .Select(Projections.Max<SiteItemOnHand>(y => y.lastmodifiedtimestamp));

var siteItems = Session.QueryOver<SiteItemOnHand>(() => siAlias)
    .Where(x => x.Businessunitid == siteID)
    .AndRestrictionOn(x => x.ItemID).IsIn(itemIdList.ToArray())
    .WithSubquery.Where(x => siAlias.lastmodifiedtimestamp == subQuery.As<DateTime>())
    .List();

这里的目标是使用子查询来过滤每个组的正确最大日期,然后使用它来过滤实际记录。

生成的SQL如下所示:

SELECT <field_list> FROM InventoryItemBUOnHand 
WHERE Businessunitid = 829
AND inventoryitemid in (939, 940, 950)
AND this_.lastmodifiedtimestamp = 
   (SELECT max(this_0_.lastmodifiedtimestamp) as y0_ 
       FROM InventoryItemBUOnHand this_0_ 
       WHERE this_0_.Businessunitid = this_.Businessunitid and this_0_.ItemID = this_.ItemID) 

警告::如果两个记录对于相同的lastmodifiedtimestampbusinessunitid具有相同的值,则比较inventoryitemid可能会导致不良结果。如果发生这种情况,您可以添加OrderBy并仅选择第一条记录。如果inventoryitemonhandid是唯一索引,它将变得更加简单。