ソートで躓いています:;

タグの編集
投稿者 カロリーメートチーズ味  () 投稿日時 2009/2/22 04:26:37
こんばんわ。こないだも同じような質問をこの掲示板で致しましたが
どうにもソートで1週間ほど躓いています:;
環境はvb2008,windows vistaです。
SQLCm.CommandText = "select * FROM 会員マスタ order by 総合点数 DESC"

        Cn.Open()
        SQLCm.ExecuteNonQuery()
        Cn.Close()
        MsgBox("並べ替えしました")


        SQLCm.CommandText = "select name from keibayosou"
        Dim value As String
        Cn.Open()
        value = SQLCm.ExecuteScalar
        Cn.Close()
        MsgBox(value)
やりたいことは データをソートして一番点数が高い人の名前を抽出したいです。
しかし上記のプログラムだと 佐藤=50点→鈴木100点の順番でデータベースに書き込んでも
変数valueには佐藤が入っています。鈴木=100点→佐藤=50点の順番に書き込むと鈴木がでます。書き込んだ順番のデータの一番上が変数valueに入ってしまいます。
こないだも同じような内容で書き込みをしましたが、どうしてもプログラムを完成させたいので是非ご教授お願いします。
投稿者 るきお  (社会人) 投稿日時 2009/2/22 05:44:28
こんにちは。
ORDER BYによる並び順の指定は、そのORDER BYを使ってデータを読み込むときにのみ作用し、そうでない場合の順番は保証されていません。
Access側はORDER BYが発行されるたびに一生懸命並び替えをしており、並び替えた結果を次回のためにとっておくということはしません。


ですので、カロリーメートチーズ味さんのプログラムでは
value = SQLCm.ExecuteScalar
として値をとってきていますが、このSQLCmにセットされているSQL文は
SQLCm.CommandText = "select name from keibayosou"
となっており、ORDER BYが指定されていないため並び順がランダムになります。

多分以下のようすると望みどおりになるのではないでしょうか?
※点数をあらわす列名を仮に「点数」としてみました。keibayosouテーブルの構造によってはうまくいかない場合もあります。
    SQLCm.CommandText = "select name from keibayosou order by 点数 desc"
    Dim value As String
    Cn.Open()
    value = SQLCm.ExecuteScalar
    Cn.Close()
    MsgBox(value)
投稿者 るきお  (社会人) 投稿日時 2009/2/22 05:53:49
補足です。
AccessやSQL Serverなど製品によって仕様は異なりますが、
厳密にいえば、ORDER BYで並び変えた結果を一時的にキャッシュすることもありますし、ORDER BYを指定しなかった場合の並び順を独自のルールで保障している場合もありますが、
細かい話をしているとかなり話が膨らみますし、今回のご質問の内容ではここまで知っておく必要はないので割愛しました。
投稿者 カロリーメートチーズ味  (その他) 投稿日時 2009/2/22 07:13:48
るきお様早速の回答ありがとうございました。
言われたとおり データを持ってくる時も orderbyしたら希望通りの動きになりました。
非常に的確なアドバイスありがとうございます
恥ずかしながら一度orderbyを使うと並び替えた結果を次回のために取って置いてくれるものだと思ってました…
 追加質問で恐縮なんですが10人登録したとして2番目に点数が高い人を取り出したいときには
SQLCm.CommandText = "select name(1) from keibayosou order by 点数 desc"でできると思ってたんですがエラーが出てしまいました 
式に未定義関数  'name' があります。
連続質問で申し訳ないですがお時間がありましたらご教授お願いいたします。
投稿者 るきお  (社会人) 投稿日時 2009/2/22 07:26:43
こんにちは。

カロリーメートチーズ味さんのプログラムでは、値をとってくるのにExecuteScalarメソッドを使用しているので、せっかく並び替えをしても先頭の値以外すべて捨ててしまいます。

2番目の値を先頭にするようにSQL文をいじることもできますが素直ではありません。
複数の値が必要な場合は、ExecuteScalarではなく、OleDbDataAdapterクラスのFillメソッドなどを使ってごっそり持ってくるのが楽です。

以下の例では先頭の値と、その次の値を表示します。
取得したデータはすべてTableの中に入っており、Table.Rows(0)が1行目、Table.Rows(1)が2行目…とあらわしています。

   
 '▼データ取得  
    Dim Cn As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Database\Animals.mdb")
    Dim SQLCm As OleDbCommand = Cn.CreateCommand
    Dim Adapter As New OleDbDataAdapter(SQLCm)
    Dim Table As New DataTable

    '説明の五十音順に並び替える。  
    SQLCm.CommandText = "SELECT 説明 FROM T_目マスタ ORDER BY 説明"
    Adapter.Fill(Table)

    '▼値の表示  
    Dim Value As String

    '先頭の値を表示  
    Value = Table.Rows(0)("説明")
    MsgBox(Value)

    '2番目の値を表示 
    Value = Table.Rows(1)("説明")
    MsgBox(Value)

    '▼後処理  
    Table.Dispose()
    Adapter.Dispose()
    SQLCm.Dispose()
    Cn.Dispose()


>SQLCm.CommandText = "select name(1) from keibayosou order by 点数 desc"でできると思っ
>てたんですがエラーが出てしまいました 
>式に未定義関数  'name' があります。
name(1)という書き方はなにを参考にされたのでしょうか???
あてずっぽうだとしたらある程度経験がないと無理だと思います。経験がないうちはヘルプや書籍などをちゃんとよんで基本的な構造や構文を理解した方が早いですよ。
投稿者 オショウ  (社会人) 投稿日時 2009/2/23 05:29:42
OleDataAdapterやOleDataReader使うのは、データの読み出し方法に関わる部分
なので直接的にと言うのであれば、SQL文として

SELECT TOP 2 説明 FROM T_目マスタ ORDER BY 説明

で、ソート条件に従い、1番目と2番目の2レコードを抽出できます。

TOP 10 とすれば、10番目まで~

試してみて下さい。

以上。
投稿者 aetos  (社会人) 投稿日時 2009/2/27 21:01:29
こっちにも返事をくださいね。
http://hpcgi1.nifty.com/MADIA/vbnet/wwwlng.cgi?print+200902/09020016.txt