Nhibernate 3.0 IQueryOver группирует и выбирает одну целую запись в каждой группе, которая удовлетворяет условию - PullRequest
0 голосов
/ 31 января 2019

Мое требование - извлечь записи SiteItemOnHand, сгруппировать по Businessunitid, inventoryitemid и получить полную запись SiteItemOnHand в каждой группе, имеющей max (lastmodifiedtimestamp)

Я пытаюсь написать эквивалентный запрос nhibernate для приведенного нижеsql query

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 голосов
/ 31 января 2019

Если я вас правильно понимаю, у вас есть такие данные, и вы хотите помеченные записи.Я не знаю, является ли 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|

Если да, то я бы использовал подзапрос, как в этом вопросе: SO: NHibernate - Выберите полные записи из агрегатов

Изменено (не проверено)в соответствии с вашими требованиями это будет выглядеть примерно так:

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) 

Внимание: Сравнение lastmodifiedtimestamp может привести к нежелательным результатам, если две записи имеют одинаковые значения для одинаковых businessunitid и inventoryitemid.Если это может произойти, вы можете добавить OrderBy и выбрать только первую запись.Это становится еще проще, если inventoryitemonhandid является уникальным индексом.

...