GroupBy SqlFunction on QueryOver

本文关键字:QueryOver on SqlFunction GroupBy | 更新日期: 2023-09-27 18:35:50

>我有一个所有不同帐户名称前缀(a-z)的列表,我使用以下命令获取

var accounts = this.SessionManager.GetActiveSession().QueryOver<Account>();
var q = accounts.Select(Projections.Distinct(
        Projections.SqlFunction("substring", 
                                NHibernateUtil.String, 
                                Projections.Property("Name"),
                                Projections.Constant(1),
                                Projections.Constant(1))));

但是,我想做的不是返回不同的列表,而是对前缀进行分组并返回以该前缀开头的帐户数,但我不确定如何使用查询来执行组,因为它不像标准 linq 那么简单。

我之所以使用 QueryOver 而不是 Query,是因为由于某种原因,子字符串函数是在内存中而不是在数据库服务器上执行的。

这就是我通常的做法

var prefixes = (from acc in this.SessionManager.GetActiveSession().Query<Account>()
              group acc by acc.Name.Substring(0, 1)
              into grp
              select new
                       {
                         Prefix = grp.Key,
                         Count = grp.Count()
                       });

编辑这是我尝试过的,但我收到以下错误

表达式 SqlFunction("substring", NHibernateUtil.String, new [] {Property("Name"), Constant(Convert(1)), Constant(Convert(1))})

var accounts = this.SessionManager.GetActiveSession().QueryOver<Account>().Select(
            Projections.Group<string>(x => Projections.SqlFunction("substring", NHibernateUtil.String,
                                                       Projections.Property("Name"), Projections.Constant(1),
                                                       Projections.Constant(1))),
            Projections.Count<string>(x => Projections.SqlFunction("substring", NHibernateUtil.String,
                                                       Projections.Property("Name"), Projections.Constant(1),
                                                       Projections.Constant(1)))
          );

GroupBy SqlFunction on QueryOver

如果所有其他方法都失败了,您可以使用Projections.SqlGroupProjection 来执行此操作!

var accounts = _busDb.Session.QueryOver<QueueEntity>()
        .Select(
            Projections.SqlGroupProjection(
                "SUBSTRING({alias}.Name, 1) as FirstChar", 
                "SUBSTRING({alias}.Name, 1)",
                new[] {"FirstChar"},
                new[] {NHibernateUtil.String}),
            Projections.Count("id"));
第一个参数是在选择中选择的内容,第二个参数是分组依据,第三个参数是

所选列的名称,第四个参数是要选择的数据类型。

你的列表有多大?如果小于 1000,我会从 sql server 收集项目列表,然后通过对列表的查询来执行常规组

var sqlout= (from acc in this.SessionManager.GetActiveSession().Query<Account>()
          select new
                   {
                     Name = acc.Name,
                     col1= acc.col1
                   }).TolList();

然后

var prefixes = (from acc in sqlout
          group acc by acc.Name.Substring(0, 1)
          into grp
          select new
                   {
                     Prefix = grp.Key,
                     Count = grp.Count()
                   });

子字符串函数将在这里工作,因为它在 c# 列表上运行,而不是在 sql 服务器上运行

您是否考虑过通过将名称的第一个字符存储在单独的列中来消除对子字符串查询的需求?

假设您使用的是 SQL Server,则可以将其设置为持久计算列,以避免更新插入/更新表的代码。

添加包含此列的索引的功能也应该有助于提高查询性能。