NHibernate 2.1:使用Alias(ICriteria)在SubQuery上进行LEFT JOIN

Rai*_*tef 6 nhibernate alias criteria subquery left-join

我基本上尝试使用NHibernate ICriteria接口创建此查询:

SomeTable 1:n AnotherTable

SomeTable有列:PrimaryKey,NonAggregateColumn
AnotherTable有列:PrimaryKey,ForeignKey,AnotherNonAggregate,YetAnotherNonAggregate

SELECT 
      table1.NonAggregateColumn, 
      subquery.SubQueryAggregate1, 
      subquery.SubQueryAggregate2
FROM 
      SomeTable AS table1
      LEFT JOIN
      (
          SELECT 
                table2.ForeignKey,
                COUNT(table2.AnotherNonAggregate) AS SubQueryAggregate1,
                AVG(table2.YetAnotherNonAggregate) AS SubQueryAggregate2
          FROM AnotherTable AS table2
          GROUP BY (table2.ForeignKey)
      ) AS subquery ON subquery.ForeignKey = table1.PrimaryKey
Run Code Online (Sandbox Code Playgroud)

很明显,使用Projection子查询效率不高,因为SQL必须扫描两次表(每个聚合一个投影子查询).

使用多个GROUP BY也不高效.

这有解决方案吗?到目前为止,我一直在使用原始SQL,但这对复杂的报告来说变得难以处理.

Ste*_*ger 2

不幸的是,标准有点受限。

尝试这个:

session.CreateCriteria(typeof(SomeTable), "st")
  .SetProjection( Projections.ProjectionList()
    .Add(Projections.GroupProperty("st.id"))
    .Add(Projections.GroupProperty("st.NonAggregateColumn"))
    .Add(Projections.RowCount(), "rowcount")
    .Add(Projections.Avg("at.YetAnotherNonAggregate"), "avg"));
  .CreateCriteria( "st.OtherTables", "at", JoinType.InnerJoin)
  .List<object[]>();
Run Code Online (Sandbox Code Playgroud)

你可能需要玩一下,这更多的是猜测。这也可能是不可能的。

它应该产生这样的结果:

select
  st.id,
  st.NonAggregateColumn,
  count() as "rowcount",
  avg(at.YetAnotherNonAggregate) as "avg"
from
  SomeTable st inner join AnotherTable at on ...
group by
  st.id,
  st.NonAggregateColumn
Run Code Online (Sandbox Code Playgroud)

一般来说:

  • 您可以使用 进行子查询DetachedCriteria。请参阅文档了解更多详细信息。
  • 您无法在 where 子句中使用 Criteria 和过滤器创建笛卡尔积。(这只适用于 HQL)。
  • 子查询不能添加到 from 子句中(因为这会导致笛卡尔积)。您只能将它们放入 where 子句(inexists
  • 您可能可以从 开始AnotherTable并导航到SomeTable. 这可能是一个替代解决方案。