简体   繁体   中英

Get last N elements for each group

What I'm trying to do is grab the last N elements (for my example 3) for each grouping in the table. My table is:

create table application_sessions
(
    application_session_id int identity(1,1) primary key,
    session_type_id int not null references session_types(session_type_id),
    start_ts datetime not null,
    end_ts datetime null,
    is_successful bit not null default 0
)

In this case, I'm trying to get the last 3 entries in the table (ordered by start_ts) for each session_type_id. To do this in SQL, I would run this:

;with ranking as
(
    select *, row_number() over (partition by session_type_id order by start_ts desc) as rn
    from application_sessions
)
select * from ranking
where rn <= 3

I'm having some issues using NHibernate with fetching these records from the database in this way. What would be the best way to do this given the Entity below (SessionType is an enum)?

public class ApplicationSession
{
    public virtual int Id { get; set; }
    public virtual SessionType SessionType { get; set; }
    public virtual DateTime StartTimestamp { get; set; }
    public virtual DateTime? EndTimestamp { get; set; }
    public virtual bool IsSuccessful { get; set; }
}

My (failing) first attempt was this:

public IList<ApplicationSession> GetLastNGroupedSessions(int count)
  {
     return _session.Query<ApplicationSession>()
                       .GroupBy(x => x.SessionType)
                       .SelectMany(y =>
                               y.OrderByDescending(z => z.StartTimestamp)
                                .Take(count))
                       .ToList();
   }

This yields the exception: Query Source could not be identified: ItemName = y, ItemType = System.Linq.IGrouping`2[RIMS.ECMS.BusinessObjects.Local.Models.SessionType,RIMS.ECMS.BusinessObjects.Local.Models.ApplicationSession], Expression = from IGrouping`2 y in {value(NHibernate.Linq.NhQueryable`1[RIMS.ECMS.BusinessObjects.Local.Models.ApplicationSession]) => GroupBy([x].SessionType, [x])}

So, it may not be the "best" solution, but it a working one. One of my coworkers pointed out that NHibernate allows for you to directly execute SQL using CreateSQLQuery. This is the solution that I came up with that works in case anyone else runs into this type of problem.

  public IList<ApplicationSession> GetLastNGroupedSessions(int count)
  {

     var sqlQuery = string.Format(@";with ranking as
     (
     select *, row_number() over (partition by session_type_id order by start_ts desc) as rn
     from application_sessions
     )
     select app.application_session_id,
        app.session_type_id,
        app.start_ts,
        app.end_ts,
        app.is_successful 
     from ranking as app
     where rn <= {0}", count);

     return _session.CreateSQLQuery(sqlQuery)
        .AddEntity("app", typeof(ApplicationSession))
        .List<ApplicationSession>();
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM