NHibernate 2.1:使用别名对子查询进行 LEFT JOIN (ICriteria)

发布于 2024-08-03 13:55:16 字数 934 浏览 6 评论 0原文

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

SomeTable 1:n AnotherTable

SomeTable has columns: 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,但这对于复杂的报告来说变得很笨拙。

I am basically trying to create this query with NHibernate ICriteria interface:

SomeTable 1:n AnotherTable

SomeTable has columns: PrimaryKey, NonAggregateColumn
AnotherTable has columns: 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

It is clear that using Projection subquery is not very efficient, since SQL has to scan the table twice (one projection subquery per aggregate).

Using multiple GROUP BYs is not efficient as well.

Is there a solution for this ? So far I've been resorting to using raw SQL but this is getting unwieldy for complex reports.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

秋凉 2024-08-10 13:55:16

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

试试这个:

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。这可能是一个替代解决方案。

Unfortunately, Criteria is a bit restricted.

Try this:

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

You probably need to play around a bit, it's more of a guess. It also might be impossible this way.

It should produce something like this:

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

Generally:

  • You can make subqueries using DetachedCriteria. See the docs for more details.
  • You can't make a cartesian product with Criteria and filter in the where clause. (This only works with HQL).
  • Subqueries can not be added to the from clause (because that would result in a cartesian product). You can only put them to the where clause (in, exists etc.)
  • You could probably start with AnotherTable and navigate to SomeTable. This might be a alternative solution.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文