ページ

2011年4月9日土曜日

◆LINQで見出し、明細、合計を出力するグループ処理

明細データを出力しながら、グループタイトルとグループ合計を出力するような処理は帳票でよく見られる。
そのようなパターンをLINQでやってみたいと思う。

  1. //見出し、明細、合計を出力するグループ処理  
  2. public void linqGroupList(Form1 form)  
  3. {  
  4.     using (PubsDataContext pubs = new PubsDataContext())  
  5.     {  
  6.         pubs.Log = Console.Out;  
  7.         var titleGroup = pubs.titles.GroupBy(t => t.pub_id)  
  8.                                     .Select(g => new  
  9.                                     {  
  10.                                         pub_id = g.Key,  
  11.                                         PriceSum = g.Sum(t => t.price),  
  12.                                         titlesData = g  
  13.                                     });  
  14.         foreach (var tg in titleGroup)  
  15.         {  
  16.             Console.WriteLine("◆" + tg.pub_id + "◆");  
  17.             foreach (var t in tg.titlesData)  
  18.             {  
  19.                 Console.WriteLine(string.Format("- {0} \t {1} \t {2}", t.title_id, t.title, t.price));  
  20.             }  
  21.             Console.WriteLine("-- 合計金額 --(" + tg.PriceSum + ")");  
  22.         }  
  23.     }  
  24. }  

基本的にはMTG Blog: ◆LINQでマスターを使わないグループ集計でやったLINQと同じパターンで集計している。
明細出力用に、titlesDataとしてtitleクラスのコレクションをグループ毎に保持している。
あとは自前でループを回しながらグループタイトルとそのなかの明細を出力している。


結果は以下のとおり。


  1. SELECT [t0].[title_id], [t0].[title], [t0].[type], [t0].[pub_id], [t0].[price], [t0].[advance], [t0].[royalty], [t0].[ytd_sales], [t0].[notes], [t0].[pubdate]  
  2. FROM [dbo].[titles] AS [t0]  
  3. WHERE ((@x1 IS NULLAND ([t0].[pub_id] IS NULL)) OR ((@x1 IS NOT NULLAND ([t0].[pub_id] IS NOT NULLAND (@x1 = [t0].[pub_id]))  
  4. -- @x1: Input Char (Size = 4; Prec = 0; Scale = 0) [0736]  
  5. -- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1  
  6.   
  7. ◆0736◆  
  8. - BU2075     You Can Combat Computer Stress!     2.9900  
  9. - PS2091     Is Anger the Enemy?     10.9500  
  10. - PS2106     Life Without Fear   7.0000  
  11. - PS3333     Prolonged Data Deprivation: Four Case Studies   19.9900  
  12. - PS7777     Emotional Security: A New Algorithm     7.9900  
  13. -- 合計金額 --(48.9200)  
  14. SELECT [t0].[title_id], [t0].[title], [t0].[type], [t0].[pub_id], [t0].[price], [t0].[advance], [t0].[royalty], [t0].[ytd_sales], [t0].[notes], [t0].[pubdate]  
  15. FROM [dbo].[titles] AS [t0]  
  16. WHERE ((@x1 IS NULLAND ([t0].[pub_id] IS NULL)) OR ((@x1 IS NOT NULLAND ([t0].[pub_id] IS NOT NULLAND (@x1 = [t0].[pub_id]))  
  17. -- @x1: Input Char (Size = 4; Prec = 0; Scale = 0) [0877]  
  18. -- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1  
  19.   
  20. ◆0877◆  
  21. - MC2222     Silicon Valley Gastronomic Treats   19.9900  
  22. - MC3021     The Gourmet Microwave   2.9900  
  23. - MC3026     The Psychology of Computer Cooking        
  24. - PS1372     Computer Phobic AND Non-Phobic Individuals: Behavior Variations     21.5900  
  25. - TC3218     Onions, Leeks, and Garlic: Cooking Secrets of the Mediterranean     20.9500  
  26. - TC4203     Fifty Years in Buckingham Palace Kitchens   11.9500  
  27. - TC7777     Sushi, Anyone?      14.9900  
  28. -- 合計金額 --(92.4600)  
  29. SELECT [t0].[title_id], [t0].[title], [t0].[type], [t0].[pub_id], [t0].[price], [t0].[advance], [t0].[royalty], [t0].[ytd_sales], [t0].[notes], [t0].[pubdate]  
  30. FROM [dbo].[titles] AS [t0]  
  31. WHERE ((@x1 IS NULLAND ([t0].[pub_id] IS NULL)) OR ((@x1 IS NOT NULLAND ([t0].[pub_id] IS NOT NULLAND (@x1 = [t0].[pub_id]))  
  32. -- @x1: Input Char (Size = 4; Prec = 0; Scale = 0) [1389]  
  33. -- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1  
  34.   
  35. ◆1389◆  
  36. - BU1032     The Busy Executive's Database Guide     19.9900  
  37. - BU1111     Cooking with Computers: Surreptitious Balance Sheets    11.9500  
  38. - BU7832     Straight Talk About Computers   19.9900  
  39. - PC1035     But Is It User Friendly?    22.9500  
  40. - PC8888     Secrets of Silicon Valley   20.0000  
  41. - PC9999     Net Etiquette     
  42. -- 合計金額 --(94.8800)  

結果は良さそうだが、発行されているSQLを見ると先頭及びグループ出力ごとに発行されているのが判る。
LINQは、それ自身を定義したタイミングでSQLを発行するのではなく実際にデータ必要になったときに発行される仕組みになっているらしい。(遅延ロード機能)
そこら辺を最適化してあげる必要がありそうだが、それはまたあとで検討(勉強)する。

0 件のコメント:

コメントを投稿

私が最近チェックした記事