2017-10-31 29 views
0

私はlinqに翻訳したいと思う次の質問があります。Linq to SQL - 複数の結合、集計、グループ化を持つクエリ

SELECT 
SUM(Credits.CreditAmount) 
,Transactions.Id 
,Person.FullName 
,Person.Id 
FROM 
Person 
JOIN 
Transactions 
ON Person.AccountId = Transactions.AccountId 
JOIN Credits 
ON Transactions.Id = Credits.TransactionId 
WHERE 
Person.Type = 'AccountHolder' 
AND Person.Status = 'Active' 
AND Transactions.CancelledDate IS NULL 
AND Credits.CancelledDate IS NULL 
GROUP BY Transactions.AccountId, Person.FullName, Person.Id 
HAVING SUM(Credits.CreditAmount) > 20 

これは私が思いついたものです。それは絶対的な豚です...それが生成するSQLはひどいものでなければなりません。

var query = from p in Person 
      join t in Transactions 
      on p.AccountId equalas t.AccountId 
      join c in Credits 
      on t.TransactionId = c.TransactionId 
      where p.Status == "Active" && 
      p.Type = "AccountHolder" && 
      t.CancelledDate == null && 
      c.CancelledDate == null 
      group new { c.CreditAmount, t.AccountId, p.FullName, p.Id } by new { t.AccountId, p.FullName, p.SSN } into grp 
      let sumC = grp.Select(x => x.CreditAmount).Sum() 
      select new 
      { 
       TotalCredit = sumC, 
       AccountId = grp.Key.AccountId, 
       FullName = grp.Key.FullName, 
       Id = grp.Key.Id 
      }; 
query.Where(p => p.TotalServiceCredit > 20); 

SQLクエリは約3秒で実行されますが、Linqクエリを完了させるための辛抱強さはまだありません。私は何か別のものがあるかどうか私は "グループ、合計、これを達成するためにやっている必要がありますか"私は書くしようとしているクエリがあるのだろうか? Linqがより多くのperformat SQLを生成するのを助けるために私ができることはありますか?

UPDATE

はsgmooreが正しい考えを持っていたが判明します。パフォーマンス問題の鍵は彼の答えでした。

この

let sumC = grp.Select(x => x.CreditAmount).Sum() 

この

TotalCredit = grp.Sum(x => x.CreditAmount) 

の違いはしていません終了したクエリとの違いでした。

SQLとほぼ同じ時間に完了した私の改訂LINQクエリ(SQLの5.3秒とLINQの5.6秒)を参照してください。

var query = from p in Person 
     join t in Transactions 
     on p.AccountId equalas t.AccountId 
     join c in Credits 
     on t.TransactionId = c.TransactionId 
     where p.Status == "Active" && 
     p.Type = "AccountHolder" && 
     t.CancelledDate == null && 
     c.CancelledDate == null 
     group new { c.CreditAmount, t.AccountId, p.FullName, p.Id } by new { t.AccountId, p.FullName, p.SSN } into grp 
     select new 
     { 
      TotalCredit = grp.Sum(x => x.CreditAmount), 
      AccountId = grp.Key.AccountId, 
      FullName = grp.Key.FullName, 
      Id = grp.Key.Id 
     }; 
query.Where(p => p.TotalServiceCredit > 20); 

ありがとうございました!

+0

なぜSQLクエリをLINQに変換しようとしていますか? SQLが高速で実行されている場合、なぜ良いことを妨げるのでしょうか? –

+0

私はLINQの理解を深めるための学習練習として使っています。もちろん、あなたの提案は実用的な解決策ですが、「LINQを使用しないでください」はLINQについて学ぶのに役立ちません。これは、比較的単純な集約クエリです。私は単にLINQを使ってこれを達成する方法に興味があります。 – Nick

+0

非常に良い。あなたは両方から同じ結果を得ますか?パフォーマンスの問題からLINQの行を返さないようにしてください。 –

答えて

1

その後、あなたはLINQが1にこれを組み合わせるせることができます私はWEI_DBAさんのコメントに反対していないが、あなたはこれを行う必要がある場合、あなたはそれが簡単に複数のクエリにこれを破るために見つけるかもしれない、例えば

var query1 = from p in Person 
     join t in Transactions on p.AccountId equals t.AccountId 
     join c in Credits on t.TransactionId equals c.TransactionId 

     where p.Status == "Active" && 
     p.Type = "AccountHolder" && 
     t.CancelledDate == null && 
     c.CancelledDate == null 
     select new { c.CreditAmount, t.AccountID, p.FullName, p.Id}; 


    var query2 = (from p in query1 
     group p by new { p.AccountId, p.FullName, p.Id } into grp 

     select new 
     { 
      TotalCredit = grp.Sum(x => x.CreditAmount), 
      AccountId = grp.Key.AccountId, 
      FullName = grp.Key.FullName, 
      Id   = grp.Key.Id 
     }; 


    var query3 = (from p in query2 where p.TotalCredit > 20 select p); 

sqlコマンド。

いつものように、生成された実際のTSQLを確認して確認することをお勧めします。

+0

ありがとう、私はそれをチェックアウトします! – Nick

関連する問題