ページ

2011年4月9日土曜日

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

明細データを出力しながら、グループタイトルとグループ合計を出力するような処理は帳票でよく見られる。
そのようなパターンを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 件のコメント:

コメントを投稿

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