6

我有一个我使用获取的所有不同帐户名称前缀 (az) 的列表

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))));

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

我使用 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)))

          );
4

3 回答 3

4

如果一切都失败了,您可以使用 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"));

第一个参数是 select 中选择的内容,第二个参数是分组依据,第三个参数是所选列的名称,第四个参数是所选数据的类型。

于 2012-06-01T12:29:53.700 回答
3

你的名单有多大?如果小于 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# list 上而不是在 sql server 上运行

于 2012-05-31T17:18:01.100 回答
3

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

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

添加包含此列的索引的能力也应该可以帮助您提高查询性能。

于 2012-06-01T12:42:28.997 回答