DataTableをForEachでGroupByするには?

解決


唯香  2010-01-14 03:23:51  No: 146686

いつも参考にさせていただいています。

DBからデータテーブルを作成し
条件にあったデータをループして
データを転記する処理を作成しています。
For Each row As DataRow In From r In tbl.Rows _
                          Where r("フィールド") = "条件"
    '転記処理
Next

その後tblをコードでグループ化したデータが欲しいので
For Each row As DataRow In From r In tbl.Rows _
                          Group By r("コード")
としたところGroupとByの間に「要素のエイリアス」
というものが必要のようでエラーになりました。
(最後にIntoも足りないようです)
どのように指定すればよいのでしょうか?

あと別件なのですが
tbl.Compute("MAX(コード)", "《条件》")で
最大値がとれることがわかったのですが
コレ↓はなぜエラーなのでしょうか?
tbl.Select("《条件》").Max
私が思っているものと違うMaxなのでしょうか?
GroupByとかもあったので使えると思ったんですが‥

とんちんかんなことを申し上げているのかもしれませんが
何かヒントだけでもご存知の方はご教授いただけるとありがたいです。

vb2008/winform


魔界の仮面弁士  2010-01-14 04:24:33  No: 146687

> その後tblをコードでグループ化したデータが欲しいので

具体的には、どういう内容のデータをどのようにグループ化したいのでしょうか?


魔界の仮面弁士  2010-01-14 04:40:29  No: 146688

とりあえずサンプル。

Sub Main()
  Dim tbl = CreateDummy()

  Dim q = From row In tbl.Rows Group By Code = row("COL1") Into Hoge = Group

  Console.WriteLine("===グループ化===")
  Console.WriteLine(String.Format("{0}件", q.Count))
  For Each z In q
    Console.WriteLine(z.Code)
  Next
  Console.WriteLine()

  Console.WriteLine("===グループの内訳===")
  For Each z In q
    Console.WriteLine(String.Format("{0}が{1}件", z.Code, z.Hoge.Count))
    For Each o In z.Hoge
      Console.WriteLine("-->" & o("COL1") & "," & o("COL2") & "/" & o("COL3"))
    Next
  Next

End Sub

Function CreateDummy() As DataTable

  Dim tbl As New DataTable()
  tbl.Columns.Add("COL1")
  tbl.Columns.Add("COL2")
  tbl.Columns.Add("COL3")

  tbl.Rows.Add("aaa", "111", "あああ")
  tbl.Rows.Add("aaa", "222", "いいい")
  tbl.Rows.Add("bbb", "123", "アアア")
  tbl.Rows.Add("bbb", "234", "イイイ")
  tbl.Rows.Add("bbb", "345", "ウウウ")
  tbl.Rows.Add("ccc", "987", "AAA")
  tbl.Rows.Add("ccc", "654", "BBB")

  Return tbl
End Function


唯香  2010-01-14 05:19:41  No: 146689

魔界の仮面弁士様お返事ありがとうございます。

サンプルまで用意していただき感謝しております。
GroupByの文法がわからなかったのですがとても参考になりました。
Group By 変数1 = row("フィールド1") {,変数2=row("フィールド2")‥} Into 変数 = Group

いつもWhereとかOrderByしかしないので気づきませんでしたが
GroupByにすると匿名型になってしまうんですね。

魔界の仮面弁士様に教えていただいたデータの取り方でやってみようと思います。
本当にありがとうございました。


魔界の仮面弁士  2010-01-14 10:23:28  No: 146690

> いつもWhereとかOrderByしかしないので気づきませんでしたが
> GroupByにすると匿名型になってしまうんですね。
匿名型になるかどうかを決めるのは、GroupBy というよりも
むしろ Select の方だと思いますよ。
匿名型になるのは、Select 句に複数のフィールドを定義した場合かと。

# Select 句を指定の指定がない場合、クエリは、現在のスコープで
# 識別される範囲変数のすべてのメンバに基づく型を返す仕様です。
http://msdn.microsoft.com/ja-jp/library/bb384607.aspx

たとえば今回の場合でいえば、

Dim q = From row In tbl.Rows _
        Group By Code = row("COL1") Into Hoge = Group _
        Select Code

などとすれば、For Each の結果は匿名型になりません。

あるいは、複数の項目を返したい場合に、
  For Each z As Foo In q
のように、型を明示したいのであれば、

  Class Foo
    Public A As String
    Public B As Integer
    Sub New(A As String, B As Integer)
      Me.A = A
      Me.B = B
    End Sub
  End Class

などの型を定義しておき、

Dim q = From row In tbl.Rows _
        Group By Code = row!COL1 Into Hoge = Group _
        Select New Foo(CStr(Code), Hoge.Count)

などという Linq 式にすれば OK です。


唯香  2010-01-15 04:45:42  No: 146691

解決後も気に留めてくださりありがとうございます。
魔界の仮面弁士様のおかげで今日やっとこんな感じで処理できました。
For Each row In From r In tbl.Rows _
               Group By COL1 = r("COL1"), COL3 = r("COL3") Into g = Group _
              Select Code = CStr(COL1), Name = CStr(COL3), Cnt = g.Count
    Console.WriteLine(String.Format("{0}-{1}-{2}", row.Code, row.Name, row.Count))
Next

いくつも似たようなデータテーブルを開くのが嫌で
こちらで質問させていただいたのですが大変勉強になりました。

魔界の仮面弁士様いつも助けていただき感謝しております。


※返信する前に利用規約をご確認ください。




  


  このエントリーをはてなブックマークに追加