取得時にUNIONを利用して、NULLを優先的に取得し、その後にNOT NULLを対象にしたデータを取得したらよいかと思います。
http://okwave.jp/kotaeru.php3?q=2153615
のように、仮のカラムを作成するSQL文を利用したらよいと思います。
しかし質問者さんの状況をみると、既に取得したデータテーブルに対してのやりくりしたいのでしょうか?
であれば、考え方は一緒です。
NULL値を対象に取得し、そのあとNOT NULL値を対象に取得。あとは連結させるだけです。
↓.NET2002でのサンプルですが、よろしければどうぞです。
Sub SampleMain()
Dim l_dtb As DataTable = ダミーデータ()
Dim l_drws() As DataRow
'--データセットにマージを行い、DataRow()を取得する方法
Dim l_dst As New DataSet()
l_dst.Merge(l_dtb.Select("ID = 1 AND 有効終了日 is Null", "有効終了日 DESC, 有効開始日 DESC"))
l_dst.Merge(l_dtb.Select("ID = 1 AND 有効終了日 is Not Null", "有効終了日 DESC, 有効開始日 DESC"))
l_drws = l_dst.Tables(0).Select ← 結果
'--ArralListにデータを溜め込み、DataRow()を取得する方法
Dim l_aryList As New ArrayList()
l_aryList.AddRange(l_dtb.Select("ID = 1 AND 有効終了日 is Null", "有効終了日 DESC, 有効開始日 DESC"))
l_aryList.AddRange(l_dtb.Select("ID = 1 AND 有効終了日 is Not Null", "有効終了日 DESC, 有効開始日 DESC"))
l_drws = l_aryList.ToArray(GetType(DataRow)) ← 結果
End Sub
Function ダミーデータ() As DataTable
Dim l_dtb As New DataTable("履歴データ")
l_dtb.Columns.AddRange(New DataColumn() { _
New DataColumn("ID", GetType(Integer)), _
New DataColumn("有効開始日", GetType(DateTime)), _
New DataColumn("有効終了日", GetType(DateTime)) _
})
Dim l_date As DateTime = Now
l_dtb.Rows.Add(New Object() {1, l_date.AddDays(1), DBNull.Value})
l_dtb.Rows.Add(New Object() {1, DBNull.Value, l_date.AddDays(5)})
l_dtb.Rows.Add(New Object() {1, l_date.AddDays(7), l_date.AddDays(3)})
l_dtb.Rows.Add(New Object() {1, l_date.AddDays(4), DBNull.Value})
l_dtb.Rows.Add(New Object() {1, DBNull.Value, l_date.AddDays(2)})
Return l_dtb
End Function
お礼
環境を言うの忘れました。VS2003です。 ArrayListに溜め込む方法でうまくいきました。ありがとうございます。 #全角スペースで回答のソースが読みやすくなっていたので、一瞬みてびっくりしました。汗