6

私は基本的に、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

SQL はテーブルを 2 回スキャンする必要があるため (集計ごとに 1 つの射影サブクエリ)、射影サブクエリの使用があまり効率的でないことは明らかです。

複数の GROUP BY を使用することも効率的ではありません。

これに対する解決策はありますか?これまでのところ、生の SQL を使用することに頼ってきましたが、これは複雑なレポートでは扱いにくくなっています。

4

1 に答える 1

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

あなたはおそらく少しいじる必要があるでしょう、それはもっと推測です。このままでは無理かもしれません。

次のようなものが生成されるはずです。

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。詳細については、ドキュメントを参照してください。
  • Criteria を使用してデカルト積を作成し、where 句でフィルター処理することはできません。(これは HQL でのみ機能します)。
  • サブクエリを from 句に追加することはできません (デカルト積になるため)。where 句 (など)inにのみ配置できます。exists
  • おそらく から始めてAnotherTableに移動できSomeTableます。これは別の解決策かもしれません。
于 2009-09-04T10:27:21.767 に答える