6

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

SomeTable 1:n 另一个表

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

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

使用多个 GROUP BY 也不是很有效。

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

4

1 回答 1

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. 有关更多详细信息,请参阅文档
  • 您不能在 where 子句中使用 Criteria 和过滤器制作笛卡尔积。(这仅适用于 HQL)。
  • 不能将子查询添加到 from 子句(因为这会导致笛卡尔积)。您只能将它们放在 where 子句(inexists
  • 您可能可以从 开始AnotherTable并导航到SomeTable. 这可能是另一种解决方案。
于 2009-09-04T10:27:21.767 回答