明細データを出力しながら、グループタイトルとグループ合計を出力するような処理は帳票でよく見られる。
そのようなパターンをLINQでやってみたいと思う。
- //見出し、明細、合計を出力するグループ処理
- public void linqGroupList(Form1 form)
- {
- using (PubsDataContext pubs = new PubsDataContext())
- {
- pubs.Log = Console.Out;
- var titleGroup = pubs.titles.GroupBy(t => t.pub_id)
- .Select(g => new
- {
- pub_id = g.Key,
- PriceSum = g.Sum(t => t.price),
- titlesData = g
- });
- foreach (var tg in titleGroup)
- {
- Console.WriteLine("◆" + tg.pub_id + "◆");
- foreach (var t in tg.titlesData)
- {
- Console.WriteLine(string.Format("- {0} \t {1} \t {2}", t.title_id, t.title, t.price));
- }
- Console.WriteLine("-- 合計金額 --(" + tg.PriceSum + ")");
- }
- }
- }
基本的にはMTG Blog: ◆LINQでマスターを使わないグループ集計でやったLINQと同じパターンで集計している。
明細出力用に、titlesDataとしてtitleクラスのコレクションをグループ毎に保持している。
あとは自前でループを回しながらグループタイトルとそのなかの明細を出力している。
結果は以下のとおり。
- SELECT [t0].[title_id], [t0].[title], [t0].[type], [t0].[pub_id], [t0].[price], [t0].[advance], [t0].[royalty], [t0].[ytd_sales], [t0].[notes], [t0].[pubdate]
- FROM [dbo].[titles] AS [t0]
- WHERE ((@x1 IS NULL) AND ([t0].[pub_id] IS NULL)) OR ((@x1 IS NOT NULL) AND ([t0].[pub_id] IS NOT NULL) AND (@x1 = [t0].[pub_id]))
- -- @x1: Input Char (Size = 4; Prec = 0; Scale = 0) [0736]
- -- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1
- ◆0736◆
- - BU2075 You Can Combat Computer Stress! 2.9900
- - PS2091 Is Anger the Enemy? 10.9500
- - PS2106 Life Without Fear 7.0000
- - PS3333 Prolonged Data Deprivation: Four Case Studies 19.9900
- - PS7777 Emotional Security: A New Algorithm 7.9900
- -- 合計金額 --(48.9200)
- SELECT [t0].[title_id], [t0].[title], [t0].[type], [t0].[pub_id], [t0].[price], [t0].[advance], [t0].[royalty], [t0].[ytd_sales], [t0].[notes], [t0].[pubdate]
- FROM [dbo].[titles] AS [t0]
- WHERE ((@x1 IS NULL) AND ([t0].[pub_id] IS NULL)) OR ((@x1 IS NOT NULL) AND ([t0].[pub_id] IS NOT NULL) AND (@x1 = [t0].[pub_id]))
- -- @x1: Input Char (Size = 4; Prec = 0; Scale = 0) [0877]
- -- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1
- ◆0877◆
- - MC2222 Silicon Valley Gastronomic Treats 19.9900
- - MC3021 The Gourmet Microwave 2.9900
- - MC3026 The Psychology of Computer Cooking
- - PS1372 Computer Phobic AND Non-Phobic Individuals: Behavior Variations 21.5900
- - TC3218 Onions, Leeks, and Garlic: Cooking Secrets of the Mediterranean 20.9500
- - TC4203 Fifty Years in Buckingham Palace Kitchens 11.9500
- - TC7777 Sushi, Anyone? 14.9900
- -- 合計金額 --(92.4600)
- SELECT [t0].[title_id], [t0].[title], [t0].[type], [t0].[pub_id], [t0].[price], [t0].[advance], [t0].[royalty], [t0].[ytd_sales], [t0].[notes], [t0].[pubdate]
- FROM [dbo].[titles] AS [t0]
- WHERE ((@x1 IS NULL) AND ([t0].[pub_id] IS NULL)) OR ((@x1 IS NOT NULL) AND ([t0].[pub_id] IS NOT NULL) AND (@x1 = [t0].[pub_id]))
- -- @x1: Input Char (Size = 4; Prec = 0; Scale = 0) [1389]
- -- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1
- ◆1389◆
- - BU1032 The Busy Executive's Database Guide 19.9900
- - BU1111 Cooking with Computers: Surreptitious Balance Sheets 11.9500
- - BU7832 Straight Talk About Computers 19.9900
- - PC1035 But Is It User Friendly? 22.9500
- - PC8888 Secrets of Silicon Valley 20.0000
- - PC9999 Net Etiquette
- -- 合計金額 --(94.8800)
結果は良さそうだが、発行されているSQLを見ると先頭及びグループ出力ごとに発行されているのが判る。
LINQは、それ自身を定義したタイミングでSQLを発行するのではなく実際にデータ必要になったときに発行される仕組みになっているらしい。(遅延ロード機能)
そこら辺を最適化してあげる必要がありそうだが、それはまたあとで検討(勉強)する。
0 件のコメント:
コメントを投稿