获取每组的最后 N 个元素
Get last N elements for each group
我想要做的是为 table 中的每个分组获取最后 N 个元素(对于我的示例 3)。我的 table 是:
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
)
在这种情况下,我试图为每个 session_type_id 获取 table 中的最后 3 个条目(按 start_ts 排序)。要在 SQL 中执行此操作,我会 运行 这样做:
;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
我在使用 NHibernate 以这种方式从数据库中获取这些记录时遇到了一些问题。鉴于下面的实体(SessionType 是一个枚举),最好的方法是什么?
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; }
}
我的(失败)第一次尝试是这样的:
public IList<ApplicationSession> GetLastNGroupedSessions(int count)
{
return _session.Query<ApplicationSession>()
.GroupBy(x => x.SessionType)
.SelectMany(y =>
y.OrderByDescending(z => z.StartTimestamp)
.Take(count))
.ToList();
}
这会产生异常:
无法识别查询源: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])}
因此,它可能不是 "best" 解决方案,但它是一个有效的解决方案。我的一位同事指出 NHibernate 允许您使用 CreateSQLQuery 直接执行 SQL。这是我想出的解决方案,以防其他人遇到此类问题。
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>();
}
我想要做的是为 table 中的每个分组获取最后 N 个元素(对于我的示例 3)。我的 table 是:
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
)
在这种情况下,我试图为每个 session_type_id 获取 table 中的最后 3 个条目(按 start_ts 排序)。要在 SQL 中执行此操作,我会 运行 这样做:
;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
我在使用 NHibernate 以这种方式从数据库中获取这些记录时遇到了一些问题。鉴于下面的实体(SessionType 是一个枚举),最好的方法是什么?
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; }
}
我的(失败)第一次尝试是这样的:
public IList<ApplicationSession> GetLastNGroupedSessions(int count)
{
return _session.Query<ApplicationSession>()
.GroupBy(x => x.SessionType)
.SelectMany(y =>
y.OrderByDescending(z => z.StartTimestamp)
.Take(count))
.ToList();
}
这会产生异常: 无法识别查询源: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])}
因此,它可能不是 "best" 解决方案,但它是一个有效的解决方案。我的一位同事指出 NHibernate 允许您使用 CreateSQLQuery 直接执行 SQL。这是我想出的解决方案,以防其他人遇到此类问题。
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>();
}