6

嗨 StackOverflow 用户,

我遇到了这个问题,我有三个 QueryOver,每个都返回一个候选 ID 列表,然后我用它来带来这些候选。为此,我编写了以下代码。

        private IQueryOver<CandidateEntity, CandidateEntity> UnionPublicWithPrivateCandidates(
        IQueryOver<CandidateEntity, CandidateEntity> publicCandidates, 
        IQueryOver<CandidateEntity, CandidateEntity> privateCandidate, 
        IQueryOver<CandidateEntity, CandidateEntity> candidatesByUserRole)
    {
        return ActiveCandidatesQueryOver.Where(Restrictions.Disjunction()
                                        .Add(Subqueries
                                            .WhereProperty<CandidateEntity>(c => c.Id)
                                            .In((QueryOver<CandidateEntity>)publicCandidates.Select(c => c.Id)))
                                        .Add(Subqueries
                                            .WhereProperty<CandidateEntity>(c => c.Id)
                                            .In((QueryOver<CandidateEntity>)privateCandidate.Select(c => c.Id)))
                                        .Add(Subqueries
                                            .WhereProperty<CandidateEntity>(c => c.Id)
                                            .In((QueryOver<CandidateEntity>)candidatesByUserRole.Select(c => c.Id))));
    }

这将返回正确的结果,生成的查询如下所示

SELECT *
FROM   Applicants 
WHERE  IsActive = 1
   and (Id in (SELECT Id from **FirstQueryOver**)
         **or** Id in (SELECT Id from **SecondQueryOver**)
         **or** Id in (SELECT Id from **ThirdQueryOver**))

问题是它使用“或”。因此,查询非常缓慢。

相反,如果我写这个:

SELECT *
FROM   Applicants 
WHERE  IsActive = 1
   and (Id in (SELECT Id from **FirstQueryOver**
                     union SELECT Id from **SecondQueryOver**
                     union SELECT Id from **ThirdQueryOver**))

它几乎立即完成。

您对我应该如何重构代码以获得更好的性能有任何想法吗?

谢谢你,阿德里安。

4

2 回答 2

1

我搜索但没有找到任何东西,所以我做了以下黑客攻击:

private IQueryOver<CandidateEntity, CandidateEntity> UnionPublicWithPrivateCandidates(
                  IQueryOver<CandidateEntity, CandidateEntity> publicCandidates,
                  IQueryOver<CandidateEntity, CandidateEntity> privateCandidate,
                  IQueryOver<CandidateEntity, CandidateEntity> candidatesByUserRole)
{
    var excludedQueryCandidates = QueryOver
        .WithSubquery.WhereNotExists(((QueryOver<CandidateEntity>)publicCandidates.Select(x => x.Id)))
        .WithSubquery.WhereNotExists((QueryOver<CandidateEntity>)privateCandidate.Select(x => x.Id))
        .WithSubquery.WhereNotExists((QueryOver<CandidateEntity>)candidatesByUserRole.Select(x => x.Id));

    return QueryOver.WithSubquery.WhereNotExists((QueryOver<CandidateEntity>) excludedQueryCandidates.Select(Projections.Distinct(Projections.Id())));
}

这不是最好的解决方案,但应该可以。

于 2013-05-14T14:03:09.157 回答
0

我不能说为什么 or 与 union 有如此大的差异。sql 分析器、查询分析器和估计的执行计划应该让您更深入地了解 sql 运行查询的方式,我猜它在第一种情况下没有使用正确的索引。但是,我会尝试将您的查询重写为:

SELECT *
  FROM   Applicants  
  WHERE  IsActive = 1
    and (this_.Id in (SELECT this_0_.Id from **FirstQueryOver** 
                                          or **SecondQueryOver** 
                                          or **ThirdQueryOver**))

看看你有什么表现。

于 2012-10-03T11:39:41.813 回答