Nhibernate 3.0 IQueryOver group by 满足条件的每组取一整条记录

Nhibernate 3.0 IQueryOver group by and fetch one entire record in each group which satisfy the condition

我的要求是获取 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 查询,其中只有 returns 三列,但我需要整个记录,因为在检索记录后我需要更新。我需要获取满足上述查询的所有 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

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

如果我对你的理解正确的话,你有这样的数据并且你想要标记的记录。我不知道 iventoryitemonhandid 是否是 table 的 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|

如果是,那么我会像这个问题一样使用子查询: 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) 

警告: 当两个记录具有相同的 businessunitidinventoryitemid 的相同值时,比较 lastmodifiedtimestamp 可能会导致不需要的结果。如果发生这种情况,您可以仅在第一条记录中添加 OrderBy 和 select。如果 inventoryitemonhandid 是唯一索引,它会变得更加简单。