具有多列连接的Nhibernate子查询

时间:2014-08-27 14:34:47

标签: c# tsql nhibernate queryover

我有以下关系中的Plans和PlanVersions的数据库结构:

 +------+                  +-------------+
 | Plan |  --------------> | PlanVersion |
 +------+  1        (1..n) +-------------+

PlanVersion是跟踪所有版本更改的版本表,它有 ActiveFromData ActiveToData 列显示此版本何时处于活动状态。 Plan也可以有SubPlans,它可以及时更改,因此PlanVersion也有 ParrentPlanId 列,告诉我们当前版本的子计划是什么。

我想要的是从一段时间以来获得所有SubPlans的所有更改以及特定计划。 这个查询就是我带来的:

DECLARE @since datetime;
set @since = '2014-08-27 12:00:00.000';

DECLARE @parrentPlan bigint;
set @parrentPlan = 1;

SELECT pv.* 
FROM [dbo].[PlanVersion] pv
INNER JOIN
    /* Query Over subselect*/
    (
       SELECT PlanId, MAX(ActiveFromDate) AS MaxActiveFromDate
       FROM [dbo].[PlanVersion] pv 
       WHERE pv.ParentPlanId=@parrentPlan
       GROUP BY PlanId
    ) groupedVersions
ON pv.ParentPlanId = groupedVersions.PlanId 
    AND pv.ActiveFromDate = groupedVersions.MaxActiveFromDate
WHERE (pv.ActiveFromDate>=@since OR pv.ActiveToDate>@since) 

现在我想将其转换为Nhibernate QueryOver: 我有这个代码

var subquery = QueryOver.Of<PlanVersion>()
                    .Where(x => x.ParentPlan.Id == parrentPlanId)
                    .Select(
                         Projections.Group<PlanVersion>(e => e.ParrentPlan.Id),
                         Projections.Max<PlanVersion>(e => e.ActiveFromDate)
                    );

但我不知道如何在QueryOver中的suquery的两列上编写内连接。

注意:

  1. 我们在测试中使用Nhibernate 3.3和4.0
  2. 此查询将成为轮询的一部分,因此性能对我来说非常重要

1 个答案:

答案 0 :(得分:0)

我想说,这有解决方案。实际上我们必须使用更复杂的SQL。我已经在这里深入解释过这种方法:

因此,以下只是基于您的子查询草稿的草稿。我们正在做的是,事实上创建两个子选择(检查预期的SQL here

PlanVersion planVersion = null;

// the most INNER SELECT
var maxSubquery = QueryOver.Of<PlanVersion>()
   .SelectList(l => l
    .SelectGroup(item => item.ParentPlan.Id)
    .SelectMax(item => item.ActiveFromDate)
    )
    // WHERE Clause
   .Where(item => item.ParentPlan.Id == planVersion.ParentPlan.Id)
   // HAVING Clause
   .Where(Restrictions.EqProperty(
      Projections.Max<PlanVersion>(item => item.ActiveFromDate),
      Projections.Property(() => planVersion.ActiveFromDate)
    ));

// the middle SELECT
var successSubquery = QueryOver.Of<PlanVersion>(() => planVersion )
    // the Plan ID
    .Select(pv => pv.ParentPlan.Id)
    .WithSubquery
    .WhereExists(maxSubquery)
    ;

有了这个子查询,我们可以自己要求计划:

// the most outer SELECT
var query = session.QueryOver<Plan>()
    .WithSubquery
    .WhereProperty(p => p.Id)
    .In(successSubquery)
    .List<Plan>();

可能会有一些小错字,但草案应该给你明确答案如何......

相关问题