アプリ版:「スタンプのみでお礼する」機能のリリースについて

ある年月に一番近い大きな日付を1件取得したいと思っています。
ある年月は40000件くらいあります。
一番早く実行できる方法を探しています。

対象となるデータを全部DataTableに取得し
LINQで何度も検索するのがいいのかと思いつきました。
全部取得するときに年月を降順に指定すると
Dim datarecord = (From animal In tbData Where animal.Field(Of Date)("年月") <= ある年月 Select animal).First
で一番近い大きな年月が取得できることが保証されるのでしょうか?
それともSQLでは何も指定せずLINQで順番を指定するのが早いのでしょうか?

A 回答 (3件)

Dim datarecord = (From animal In dt Where animal.Field(Of Date)("年月") <= getCalcDate And animal.Field(Of Date)("年月") >= minCalcDate Order By animal.Field(Of Date)("年月") Descending Select animal)



For Each field In datarecord
Console.WriteLine(field("年月"))
Next

ではどうでしょうか?
    • good
    • 0
この回答へのお礼

試してみましたが効果が得られませんでした。

SQLを何回も発行するほうが何倍も早かったので
LINQはあきらめました。
環境と作り方によって変わるので
合っているものを選んでいこうと思います。

何度もお返事ありがとうございました。

お礼日時:2009/09/24 20:07

提示していただいたソースであれば、LINQのほうがダントツで早いです、なぜかというと、抽出が実行されていないからです。



LINQは遅延評価を行います、結果を参照されてたときに始めてクエリが実行される仕組みです。

そのため、
XXXXXXX
となっている部分を、何か参照するロジックに変更してください。

3回くらい参照するようにすれば、その差は歴然です。

これを解決する方法は、
datarecord.ToList<>などの変換メソッドのどれかを利用しコピーを作成してからアクセスするようにします。


話を戻します。
LINQは遅延評価ですので、参照されるたびに条件式で評価しなおします。
そのため、そのときのDataTableの内容を評価した結果を返してきます。
条件によっては参照するたびに違った結果を出すことも可能というわけです。

この回答への補足

早そうな遅延評価を実行させるように
プログラムを書き換えました。

でもうまくできませんでした。
「シーケンスに要素が含まれていません」
が表示されます。

Dim getDate As Date 'ある年月
Dim tbData As DataTable 'データ
Dim total as Decimal '合計値

tbData にテーブルデータ取得

Dim datarecord = (From animal In tbData Where animal.Field(Of Date)("年月") <= getCalcDate Order By animal.Field(Of Date)("年月") Descending Select animal).First

'対象年月分ループ
Do Until getCalcDate < 最小日付

total +=datarecord("データ")
 getCalcDate = (getCalcDate を減らす式)
Loop

補足日時:2009/09/20 10:44
    • good
    • 0

LINQは基本的には遅延評価にメリットを求めたほうがよいと思います。



速度的には列挙体を検索するのとあまり変わらないです。

DataTableにはSelectメソッドがありますことらを利用すればよいのではないでしょうか?
まずLINQより早いです。

http://www.yel.m-net.ne.jp/~oss/Tips/ADO/Tips_01 …

この回答への補足

ありがとうございます。
やってみましたがLINQの方が早く処理が終わりました。
'DataTableにSelect
Do Until getCalcDate < minCalcDate
'Dim datarecord = tbData.Select("年月<=#" & getCalcDate & "#", "年月 DESC")

'取得した1行目の合計を計算
XXXXXXXX

'次の検索する年月の作成
getCalcDate = DateAdd(DateInterval.Minute, 1, getCalcDate)
Loop

'LINQで検索
Do Until getCalcDate < minCalcDate
Dim datarecord = (From animal In tbData Where animal.Field(Of Date)("年月") <= getCalcDate Order By animal.Field(Of Date)("年月") Descending Select animal).First

'取得した1行目の合計を計算
XXXXXXXX

'次の検索する年月の作成
getCalcDate = DateAdd(DateInterval.Minute, 1, getCalcDate)
Loop

LINQをDo Uintilの外に出すと
結果が間違って返ってきます。

補足日時:2009/09/18 10:31
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!