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

时间:2009-09-03 13:55:36

标签: nhibernate criteria subquery left-join alias

我基本上尝试使用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

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

使用多个GROUP BY也不高效。

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

1 个答案:

答案 0 :(得分:2)

不幸的是,Criteria有点受限制。

试试这个:

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[]>();

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

它应该产生这样的东西:

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

一般而言:

  • 您可以使用DetachedCriteria制作子查询。有关详细信息,请参阅the docs
  • 您不能使用Criteria生成笛卡尔积,并在where子句中进行过滤。 (这仅适用于HQL)。
  • 子查询无法添加到from子句中(因为这会产生笛卡尔积)。您只能将它们放到where子句(inexists等。)
  • 您可以从AnotherTable开始,然后导航至SomeTable。这可能是另一种解决方案。