2012-10-03 6 views
6

こんにちはStackOverflowのユーザー、NHibernateは - 連合3 QueryOvers

私は3 QueryOversを持っており、それらのそれぞれが、私はそれらの候補者をもたらすために使用する候補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**)) 

それはほぼ瞬時に完了します。

パフォーマンス向上のためにコードをどのようにリファクタリングする必要がありますか?

ありがとう、 エイドリアン。

+0

メモリ内ユニオンオプションを実行していますか? –

+0

@Andrew Whitaker私はちょうどそれをやってしまったが、複数のクエリによって返されるレコードがあるので、私は手動で重複を排除する必要があるので、実際には好きではない。 –

答えて

1

ので、私は以下のハックを作りました。

0

私は、なぜ、またはvs組合がそのような相違を持っているのかは言えません。 SQLプロファイラ、クエリアナライザ、および推定実行計画は、SQLがクエリを実行するためにどのようなことを行うかをより深く理解するはずです。最初のケースで正しいインデックスを使用していないと思います。しかし、私はあなたのクエリを次のように書き直そうとしています:

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

あなたはどのようなpreformanceを持って参照してください。それが最善の解決策ではありませんが、動作するはず

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()))); 
} 

私は検索が、何も見つかりませんでした
+0

こんにちはピア、助けてくれてありがとう。 私は私の列にあるインデックスをチェックします。 しかし、C#コードのリファクタリングに関するヒントを教えていただければ幸いです。 –

関連する問題