降順で並び替えて昇順で受け取りたい

このQ&Aのポイント
  • 成績がいい人3人のレコードを昇順で取得する方法について困っています。
  • 現在sqlite3を使用しており、'select * from テーブル order by 成績 desc limit 3'というクエリを使用していますが、取得結果が順番通りにならず困っています。
  • 結果として欲しいのは、成績がいい人を降順で並び替えた後に昇順で取得することです。
回答を見る
  • ベストアンサー

降順で並び替えて昇順で受け取りたい

sqlite3 を使用しています。 名前 | 成績 A | 80 B | 65 C | 90 D | 77 E | 46 F | 30 例えば上記のようなテーブルがあったとします。 成績がいい人3人のレコードを昇順で取得したいのですが、どのようにすればいいか困っています。 select * from テーブル order by 成績 desc limit 3; だと上位3人を抽出できるのですが、いい人の順番 C | 90 A | 80 D | 77 となってしまいますよね。 そうではなく、 D | 77 A | 80 C | 90 という結果が欲しいのです。 よろしくおねがいします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.5

「TOP n」は、SQL Serverの独自機能であり、他の主要なRDBMSでは使えません。 また、分析関数も、Oracle、SQL Server 2005などのいくつかのRDBMSでしか実装されていません。 そのため、自前で行に通番を振る必要があります。 <成績上位から行に通番を付ける> select (select count(*)+1 from tbl1 where 成績>x.成績) as rownum,* from tbl1 as x; 上記のクエリで通番を付けられますから、このクエリの結果から上位3位タイまでを得るクエリを作ります。 <期待の結果を得るSQL> select 名前,成績 from(select (select count(*)+1 from tbl1 where 成績>x.成績) as rownum,* from tbl1 as x) as y where rownum<=3 order by 成績 ;

その他の回答 (10)

noname#182251
noname#182251
回答No.11

#6です。 >『) AS 式1, s.成績』 の 『式1』ってなんですか? MS-ACCESSが「勝手に」書き加えた「 AS 式1」の一部です。SQLビューで書いたSQL文をデザインビューで見るとこうなります。消せば良かったのかもしれませんが、手抜きしました。

aro_and_pooh
質問者

お礼

ありがとうございました。

回答No.10

>『) AS 式1, s.成績』 の 『式1』ってなんですか? #6さんへの質問ですが、ついでなので回答しておきます。 #6さんのSQLを、もう少し簡単に書くと、以下のようなSQLになります。 SELECT 名前,s.成績 FROM tbl1 AS s WHERE (SELECT Count(*)+1 FROM tbl1 where 成績>s.成績)<=3 ORDER BY s.成績; 「as 式1」のところは、「名前」列を指定すればいいところを、誤記されたのだと思います。 なお、やっていることは、#6さんも私も同じで、テーブルを自己結合し、成績の大きい件数をカウントし、+1することで、行に通番を振っています。 A | 80→80より大きい行数は1件 B | 65→同様に3件 C | 90→同様に0件 D | 77→同様に2件 E | 46→同様に4件 F | 30→同様に5件 それぞれ件数に+1することで、大きい順に1~6の通番を付けることができます。 その通番が3以下のもの(上位3位タイまで)を最終的な検索結果として得ています。

aro_and_pooh
質問者

お礼

「もしかして名前を入れればいいのかな?」と思って入れたのですがうまくいかなかったので質問しました。 でも入力ミスだったんでしょうね。 今日再度チャレンジすると期待する結果が得られました。 解説までしていただきましてありがとうございます。 よくわかりました。

回答No.9

>最後の 『order by 成績』 の部分は必要なのでしょうか? ほぼすべてのRDBMSは、「ORDER BY」指定がないと、検索結果の返却順序は保証していません。 「保証していないと言っているが、実はプライマリキー順や格納順になるのでは?」と考える人もいるようですが、例えば格納と削除を繰り返したり、プライマリキーの逆順やランダムな格納をすると、すぐに検索結果の順序が乱れたりします。 ジョイン、group byなどを行う場合、内部的にソートされることもありますが、その結果はRDBMS側としては保証されていませんから、内部処理が変わって順序が不定になっても、誰にも文句を言えません。

aro_and_pooh
質問者

お礼

そうですね、検索結果の順序は保証していないと見たことがありました。 ありがとうございます。

回答No.8

#5、#7です。 #7の説明で、一部、紛らわしいところがあったので、訂正します。 #7の(2)は、「予約語と同じ表名や列名、一部の特殊記号を含む表名や列名を使う場合」の説明でした。

aro_and_pooh
質問者

お礼

詳しく教えていただき、ありがとうございます。 試してみた結果、期待通りの結果が得られました。 私のレベルではとても高度な回答だったため、理解に時間がかかってしまいました。。。 それでもうひとつお伺いしたいのですが、 最後の 『order by 成績』 の部分は必要なのでしょうか? 『where rownum <= 3』 で終わっても同じ結果が得られるのでは?と思ったのですが…。 よろしければ最後の一行を付ける意味教えてください。

回答No.7

MS-ACCESSで実機確認した人は、他のRDBMS利用者から見ると、やや不思議(カッコが異様に多かったり、同じ式を繰り返し書いたり)なSQLを提示してくれることがあります。 これは、以下のような理由からですので、参考までに。 (1)「TOP n」は、SQL Server、MS-ACCESSといったマイクロソフト製品の独自機能。 (2)予約語や一部の特殊記号を使う場合、標準SQLや主要なRDBMSでは、「"」で囲む。  SQL Serverは、これに加え、[ ]を使える。  MS-ACCESSは、[ ]で囲む。  ちなみに、SQLiteでも、「"」に加え、 [ ]を使えるようです。 さらにちなみに、MySQLでは「`」を使う。 (3)MS-ACCESSでは、インラインビュー等で式に付けた別名をORDER BYや検索条件に指定できないようであり、同じ式を繰り返し書かなければならないらしい。  主要なRDBMSでは、内側のクエリで式に付けた別名を、外側のクエリで検索条件に指定できる。また、selectの選択リストで付けた別名を、ORDER BYでも指定できる。 (4)MS-ACCESSで生成されるクエリは、異様に( )が多くなる。また、JOIN等で他のRDBMSでは必要のないところにも、MS-ACCESSでは( )が必要なところがある。

noname#182251
noname#182251
回答No.6

改めて、TOPを使用しない方法 SELECT (SELECT Count(*)+1 FROM テーブル where テーブル.成績>s.成績 ) AS 式1, s.成績 FROM テーブル AS s WHERE ((((SELECT Count(*)+1 FROM テーブル where テーブル.成績>s.成績 ))<=3)) ORDER BY s.成績;

aro_and_pooh
質問者

お礼

回答ありがとうございます。 勉強不足ですみません。お伺いしたいのですが、 『) AS 式1, s.成績』 の 『式1』ってなんですか?

noname#182251
noname#182251
回答No.4

#1,#3です。質問を充分読んでおりませんでした。拙解答は無視してください。失礼いたしました

noname#182251
noname#182251
回答No.3

#1です >TOP を使わない方法ありますでしょうか? limitを使えばよろしいのでは。 要は ORDER BY 100-[成績] のような方法で何とかなりそうだと云うことです。

  • ann_dv
  • ベストアンサー率43% (528/1223)
回答No.2

SQL Server 2000で試したので、構文は多少違うと思いますが、 select * from テーブル名 where 成績 in ( select top 3 成績 from テーブル名 order by 成績 desc) order by 成績 でうまくいきました。

aro_and_pooh
質問者

お礼

早速の回答ありがとうございます。 sqlite では TOP が使えないようです。。。 TOP を使わない方法ありますでしょうか?

noname#182251
noname#182251
回答No.1

SELECT TOP 3 成績, 100-[成績] AS s FROM テーブル ORDER BY 100-[成績]; みたいなSQLで如何でしょう。Accessで試したのでTOPを使用しています。

aro_and_pooh
質問者

お礼

早速の回答ありがとうございます。 sqlite では TOP が使えないようです。。。 TOP を使わない方法ありますでしょうか?

関連するQ&A

  • PerlからMysqlに接続してデータを昇順?降順に並べる方法

    こんばんは。 現在、PerlからMysqlに接続してデータを昇順?降順に並べようと思っております。 しかし、降順に並べる場合、うまく動きません。 詳細を以下に明記しますので、どなたか宜しくお願いします。 テーブル名:test テーブル内のデータ:100個 まず、昇順の場合 少し省略しますが、まず接続します。 $dbh = DBI->connect($dsn,$user,$password); $sth = $dbh->prepare("SELECT * From test Order by no limit 5,2"); $sth->execute; $sth->finish; $dbh->disconnect; これで、no5から二つ(つまり、no5とno6のみ)が抽出されると思います。 降順の場合 $dbh = DBI->connect($dsn,$user,$password); $sth = $dbh->prepare("SELECT * From test Order by no desc limit 5,2"); $sth->execute; $sth->finish; $dbh->disconnect; こうすると、no6,no5という順に抽出されます。ちなみに、limit 5,2をlimit 5,3とすると、no6,no5,no4と抽出されます。なぜここでlimit 5,2の際にno5,no4でlimit 5,3の際にno5,no4,no3という順に抽出されないのか分かりません。 私がしたいのは、noを降順(no5,no4,no3・・・)という順に表示させたいのです。ただ、降順に表示させるのではなく、例えば上記でlimitで指定したように、あるnoから3つとかしたいのです。 質問が長くなり分かりにくいかも知れないのですが、どなたか力を貸していただけないでしょうか。 宜しくお願いします。

    • ベストアンサー
    • Perl
  • 最新のものからデータを10件づつ昇順で並べたい

    MySQLで、最新のものからデータを10件づつ昇順で並べたいと思っています。 最新のデータを1ページ10件ごとに収めていきたいので(最初のページを半端にしたくないので)、データを降順に取り出し、それぞれ取り出した10件ごとに昇順で並べ変えることが出来ないかと、いろいろ工夫をしましたが行き詰っています。PHPスクリプト(一部ですが)は次のように書いています。 $from = ($page-1)*10; $query = "SELECT * FROM table ORDER BY age DESC, sinchou DESC, taijyuu DESC LIMIT 10 OFFSET $from"; 1.降順で取り出したデータ10件を昇順に並べ替えるにはどのようにすれば良いでしょうか? 2.最新のものからデータを10件づつ昇順で並べるための良い方法が、上記の他にありますでしょうか? なにかご示唆を頂ければ有難いです。よろしくお願い致します。

    • ベストアンサー
    • MySQL
  • Accessで最新レコード20件を表示させるには

    Access2000のクエリで、最新のレコード20件を表示させたい場合どのようにしたら良いでしょうか? レコード番号があり、最新番号が100の場合、80~100を表示させたいのですが。 SQLベースだと SELECT no_c FROM table ORDER no_c DESC limit 20 など、limitが使えますが、Accessでこれに該当するものはありますか?

  • MATCHとBETWEENを併用したい

    namesテーブルのcontentsカラムにねこを含むレコードのうち、 現在までに書き込まれたものを新しいものから抽出したいと思います。 contentsはverchar(255)、unixtimeはint(11)です。 しかし、 SELECT * FROM names WHERE MATCH (contents) AGAINST ('+ねこ' IN BOOLEAN MODE) AND BETWEEN unixtime < 1360850220 ORDER BY `unixtime` DESC limit 1,50 ; が出力されません。 このSQL文はどこが間違っているのか、ご指摘ください。 SELECT * FROM names WHERE MATCH (contents) AGAINST ('+ねこ' IN BOOLEAN MODE) ORDER BY `unixtime` DESC limit 1,50 ; だと出力されるので AND BETWEEN unixtime < 1360850220 が怪しいと思うのですが、どう訂正したらいいのかわかりませんでした。 よろしくお願いいたします。

    • ベストアンサー
    • MySQL
  • 並べ替えたレコードセットをまた並べ替えたい

    宜しくお願いします。 auto_incrementの項目(SEQ)を持ったテーブル(TEST)があります。 直近10件や直近20件等のレコードを取り出すため select * from TEST order by SEQ desc limit 10 と書いたのですが、 抽出したレコードをPHPでブラウザに SEQ順に読み込み吐き出したいと思っております。 複問い合わせ等素人なりに試してみたのですが、 Every derived table must have its own aliasと怒られています。 どのようにすればよいのでしょうか。 ご教示願います、宜しくお願い致します。

  • Excelの昇順/降順で並び替えにつきまして・・・

    初歩的かもしれませんがよろしくお願いいたします。 例えば、この様な表があるとしまして・・    A     B       C     D 1  氏名 |  住所   |  品名 | 品番 2  佐藤 | ◎◎丁目 | りんご |  02 3  田中 | □□丁目 | バナナ |  04 4  鈴木 | △△丁目 | ミカン |  03 5  伊藤 | ◇◇丁目 | スイカ |  01 Dの品番を昇順/降順で並べ替えた場合にA、B、Cのデータも Dの順番と一緒に変わる方法を教えてください。 よろしくお願いいたします。

  • Arrayってなんですか?

    自分は素人でPEARを使った抽出方法とその結果の整列方法を、システム開発者に聞きましたが、やってもまったくうまくいきません。 <? $test = $DB->getAll(&quot;SELECT nicname,point FROM &quot;.$k_user_table.&quot; order by point DESC LIMIT 0,3 &quot;); print_r($test); ?> 結局こちらで教えていただいた抽出部分の $test = $DB->getAll("SELECT nicname,point FROM ".$k_user_table." order by point DESC LIMIT 0,10 "); は出たのですが、改行もなくArray等と言う訳の分からない文字がやたら出て、かなり血圧が上がります。 $test = $DB->getAll("SELECT nicname,point FROM ".$k_user_table." order by point DESC LIMIT 0,10 "); で抽出した物を、 while($row =$test->FetchRow()) {  print $row[0]; print $row[1];  print &quot;<hr>&quot;; } の様な形で整列させるためにはどうしたらよいですか? 現在まで出来てるのは、 <? $test = $DB->getAll(&quot;SELECT nicname,point FROM &quot;.$k_user_table.&quot; order by point DESC LIMIT 0,3 &quot;); print_r($test); while($row =$test->FetchRow()) {  print $row[0]; print $row[1];  print &quot;<hr>&quot;; } ?> です。 と言うか、これで出るとシステム側から言われてますが、エラーばっかり出やがります。 パソコンの中に手を突っ込んでガリガリ揃えてやりたい気分ですね。 短気な私はそろそろやばいです。

    • ベストアンサー
    • MySQL
  • 任意の上位の集計を取得するには?

    任意の上位の集計を取得するにはどうしたらよいかわかりません。初めての質問なので、うまく表現できないことをご容赦ください。 例としてテーブルを記させていただきました。 testというテーブルに以下のようにデータが入っているtestというテーブルを想定しています。u_0で降順で上位3つのu_0とa_0を取得したいのですが、 select sum(u_0),sum(s_0) order by u_0 desc limit 0,3 では当然全集計となりますので意図したものとの結果になりません。 是非、ご教授いただければ幸いです。 +--------+------+ | u_0 | s_0 | +--------+------+ | 510 | 1 | | 1701 | 9 | | 22454 | 91 | | 43271 | 148 | | 2979 | 9 | | 618 | 8 | | 161148 | 420 | | 6657 | 21 | | 12562 | 17 | | 7619 | 25 | +--------+------+ sum(u_0)=161148+43271+22454 sum(a_0)=420+148+91 取得したいのは +----------+----------+ | sum(u_0) | sum(s_0) | +----------+----------+ | 226873 | 659 | +----------+----------+ ということなのですが、よろしくお願い申し上げます。

    • ベストアンサー
    • MySQL
  • order byで並び変えし最大値の項目の抽出方法ついて

    すみません。 order byで並び変えし最大値の項目のみ一意で抽出したいのですが 、 SELECT * from ta order by no,date1,date2; no | date1 | date2 ----+-------+------- 11 | 2008 | 0501 11 | 2008 | 0502 11 | 2008 | 0502 11 | 2008 | 0503 12 | 2008 | 0501 12 | 2008 | 0502 12 | 2008 | 0503 13 | 2008 | 0501 13 | 2008 | 0502 13 | 2008 | 0503 14 | 2008 | 0501 とあった場合、 no,date1,date2のorder by順番で並び変えし 11 | 2008 | 0503 12 | 2008 | 0503 13 | 2008 | 0503 14 | 2008 | 0501 とno項目に対し一つずつだけ出力したい場合どのようにしたらよいのでしょうか? LIMITとoffsetだと1項目分しか出力されず困っております。 SELECT * from ta where no in (select no from ta group by no limit 1 offset 0) order by no,date1 desc,date2 desc limit 1; 宜しくお願い致します。

  • SQLのSELECT文でのランダム抽出について

    SQLのSELECT文でのランダム抽出について データベースSQLiteでSELECT文の結果をランダムに抽出するには ORDER BY RANDOM()を使うようですが、前回ランダムに抽出された順序と同じ結果を得るにはどのようにすればよいでしょうか。 MySQLの場合は、ORDER BY RAND(n)でnの値を同じにすれば、同じ順序で抽出できるようですが、SQLiteでは無理なようです。 今考えているのはRANDOM()で得られた列の一つ(たとえばID)を一時的に別のテーブルを作成して保存後、その一時テーブルを利用するというものですが、もっと良い方法があるのではと思います。 何か別の方法がありましたら、教えていただきたくよろしくお願いいたします。