3流プログラマのメモ書き

元開発職→社内SE→派遣で営業支援の三流プログラマのIT技術メモ書き。 このメモが忘れっぽい自分とググってきた技術者の役に立ってくれれば幸いです。(jehupc.exblog.jpから移転中)

(.Net)DataTable でソートをする(DataTable.Select)

DataTable自体にはソートをしてくれる機能がありませんが、DataTable.Select を応用することでソート処理ができます。

DataTable.Select() メソッドが DataTable の中でフィルタをかけるのに使えるということは(VB.Net)DataTableで特定の列の最大値を含む行を取得したい。(DataTable.Select)で紹介しました。

今回は純粋にソートだけを行う方法です。

問題は、DataTable.Select() メソッドは引数で指定された条件にあった DataRow 配列を返すという点です。DataTable 自体の内部のソートはしてくれません。

ということで、返り値の DataRow 配列を元に、新しい DataTable を作成するという方法をとりました。

コードはこんな感じです。

'ソート対象のテーブル作成

Dim dtbl As New DataTable()

Dim col(1) As DataColumn

col(0) = New DataColumn("ID", Type.GetType("System.Int32"))

col(1) = New DataColumn("Age", Type.GetType("System.Int32"))

dtbl.Columns.AddRange(col)

 

'データ作成

For i As Integer = 0 To 5

Dim row As DataRow = dtbl.NewRow()

row("ID") = i

dtbl.Rows.Add(row)

Next

dtbl.Rows(0)("Age") = 30

dtbl.Rows(1)("Age") = 60

dtbl.Rows(2)("Age") = 40

dtbl.Rows(3)("Age") = 50

dtbl.Rows(4)("Age") = 20

dtbl.Rows(5)("Age") = 60

 

'ソート前確認

For Each row As DataRow In dtbl.Rows

Console.WriteLine("ID:" & row("ID") & " Age:" & row("Age"))

Next

Console.WriteLine("")

 

'DataTable.Select()を使いソート(第二引数にソート条件を書く)

Dim rows As DataRow() = dtbl.Select(Nothing, "Age DESC , ID ASC").Clone()

 

'ソート後の DataTable を用意

Dim dtblSrt As New DataTable()

'ソート前テーブルの情報をクローン

dtblSrt = dtbl.Clone()

 

'ソートされてる DataRow 配列をソート後の DataTable に追加

For Each row As DataRow In rows

dtblSrt.ImportRow(row)

Next

 

'ソート後確認

For Each row As DataRow In dtblSrt.Rows

Console.WriteLine("ID:" & row("ID") & " Age:" & row("Age"))

Next

上記例だとソート前にコンソール出力した結果はこうなります。

ID:0 Age:30

ID:1 Age:60

ID:2 Age:40

ID:3 Age:50

ID:4 Age:20

ID:5 Age:60

そして、ソート後にコンソール出力するとこうなります。

ID:1 Age:60

ID:5 Age:60

ID:3 Age:50

ID:2 Age:40

ID:0 Age:30

ID:4 Age:20

しゃんと指定したとおりにソートされてますね。

ただし、この方法だと新しい DataTable を作ったり、ループを使ってるため大量のデータのときに処理速度の問題や大量メモリ消費の問題がでてきます。

もっといい方法はないですかねぇ。。

ちなみに、@IT:[ADO.NET]データテーブル(DataTable)内のレコードをソートするには?では、DataRowView.Sort メソッドを使った方法が載せられてました。ソートの方法に DataRowView.Sort メソッドを使っているという点以外は、今回紹介した方法と似たようなことになってます。

また、DataTable.Select でのソートは値に NULL があった場合、Oracle での ORDER BY と結果が異なることがあるようなので、注意が必要です。詳しくは、DataTableおよびDataViewの注意点で取り上げられてました。