如何使用 LINQ 或 HQL 执行以下 SQL 查询

Posted

技术标签:

【中文标题】如何使用 LINQ 或 HQL 执行以下 SQL 查询【英文标题】:How to execute the following SQL-Query using LINQ or HQL 【发布时间】:2011-07-03 10:32:15 【问题描述】:

如何使用 Castle ActiveRecords 和 LINQ 或 HQL 执行以下查询?

选择 a.id、s.classes、COUNT(p.id)、MAX(p.date) 作为最后一个、MIN(p.date) 作为第一个 来自帐户 a 左加入学校 s.account_id = a.id 左加入用户 u ON u.account_id = a.id LEFT JOIN 点 p ON p.user_id = u.id WHERE 付款 = "S" 按 a.id 分组

这些表以下列方式关联:

我还为所有定义了正确关系的表设置了 ActiveRecord 类(如果我按步骤进行查询,它可以工作,但它很慢,因为有很多行),我尝试了以下方法,但没有成功:

var result = from account in AccountRecord.Queryable
             join s in SchoolRecord.Queryable on account equals s.Account into schools
             from school in schools.DefaultIfEmpty(null)
             join user in UserRecord.Queryable on account equals user.Account
             join p in PointsRecord.Queryable on user equals p.User into points
             where account.PaymentType == "S"
             select new  Account = account, School = school, Count = points.Count() ;

在以下位置引发了以下The method or operation is not implemented-Exception:

NHibernate.Linq.Visitors.QueryModelVisitor.VisitGroupJoinClause(GroupJoinClause groupJoinClause, QueryModel queryModel, Int32 index)

【问题讨论】:

您是否必须按s.classes 分组才能获得有效的 SQL 查询? 不,s.classes 只是学校表的一个 int 列,表示学校的班级数量。实际上,我需要 account 和 school 表中的更多列,我在此处省略了这些列以解决主要问题,但是发布的 SQL 查询在直接针对 de DB 执行时有效。 【参考方案1】:

使用 HQL 找到了解决方案 - 我仍然愿意接受 LINQ 解决方案:

HqlBasedQuery query = new HqlBasedQuery(typeof(AccountRecord),
    "SELECT a, s, COUNT(p), MIN(p.DateUTC), MAX(p.DateUTC) " +
    "FROM AccountRecord a " +
    "LEFT JOIN a.Schools s " +
    "LEFT JOIN a.Users u " +
    "LEFT JOIN u.Points p " +
    "WHERE a.PaymentType=:payment GROUP BY a.Id");
query.SetParameter("payment", "S");
var result = from object[] row in (ArrayList)ActiveRecordMediator.ExecuteQuery(query)
                select new
                
                    Account = row[0] as AccountRecord,
                    School = row[1] as SchoolRecord,
                    Count = row[2],
                    First = (new DateTime(1970, 1, 1, 0, 0, 0, 0)).AddSeconds(Convert.ToDouble(row[3])),
                    Last = (new DateTime(1970, 1, 1, 0, 0, 0, 0)).AddSeconds(Convert.ToDouble(row[4]))
                ;

【讨论】:

我现在会接受这个/我的解决方案,因为它是我拥有 ATM 的唯一可行的解​​决方案,但我仍然想使用 LINQ...【参考方案2】:

我认为您的 Linq 查询类似于:

var result = from a in AccountRecord.Queryable
             join s in SchoolRecord.Queryable on a.id equals s.account_id
             join u in UserRecord.Queryable   on a.id equals u.account_id
             join p in PointsRecord.Queryable on u.id equals p.user_id
             where a.payment == "S"
             group by a.id
             select new
             
               Account = a,
               School = s,
               Count = p.Count()
             ;

虽然我不确定 NHibernate 将如何处理 group byCount() 组合。如果没有引发错误,您可能想看看生成的 SQL 最终是什么。

如果这不起作用,您可能需要重新选择记录,然后在应用程序中对它们进行分组/计数,更像:

var data = from a in AccountRecord.Queryable
           join s in SchoolRecord.Queryable on a.id equals s.account_id
           join u in UserRecord.Queryable   on a.id equals u.account_id
           join p in PointsRecord.Queryable on u.id equals p.user_id
           where a.payment == "S"
           select new
           
             Account = a,
             School = s,
             Count = c
           ;
var grouped = data.ToList.GroupBy(x => x.Account.Id);

【讨论】:

很抱歉回答晚了,但这给我带来了Unable to cast object of type 'Remotion.Data.Linq.Clauses.JoinClause' to type 'Remotion.Data.Linq.Clauses.FromClauseBase'.-Exception...

以上是关于如何使用 LINQ 或 HQL 执行以下 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式将 HQL 转换为 SQL 查询(不记录)

将列表传递给 HQL 或 SQL 中的 IN 子句?

如何使用 Hive 仓库连接器在 pyspark 中执行 HQL 文件

如何编写 hql/sql 来解决以下问题

如何将任何给定的 SQL/HQL 选择查询动态转换为等效计数查询?

如何在java中用hql或sql查询得到某表的所有字段名?