質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.58%

なぜ、一番上から取得するのか

解決済

回答 7

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,513

aaaaaaaa

score 481

下記のテーブルからuriaが最大のものを取得する際、

MariaDB [db1]> select * from tb;
+------+------+------+
| bang | uria | tuki |
+------+------+------+
| A103 |  101 |    4 |
| A102 |   54 |    5 |
| A104 |  181 |    4 |
| A101 |  184 |    4 |
| A103 |   17 |    5 |
| A101 |  300 |    5 |
| A102 |  205 |    6 |
| A104 |   93 |    5 |
| A103 |   12 |    6 |
| A107 |   87 |    6 |
+------+------+------+


select * from tb where uria in (select max(uria) from tb);というSQL文で取得できます。

+------+------+------+
| bang | uria | tuki |
+------+------+------+
| A101 |  300 |    5 |
+------+------+------+
1 row in set (0.04 sec)


ところでselect bang,max(uria),tuki from tb;というSQL文を発行すると

+------+-----------+------+
| bang | max(uria) | tuki |
+------+-----------+------+
| A103 |       300 |    4 |
+------+-----------+------+
1 row in set (0.00 sec)


というレコードが取得できます。
カラムbangとtukiの値は、tbテーブルの一番上の部分から、uriaは、関数の通りtbテーブル内で一番大きい数を取得しています。
ここで、素朴な疑問なのですが、なぜ、一番上の部分から取得しようとしたのでしょうか。仕様と言われるとそれまでですが、何か理由があるのでしょうか。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 7

checkベストアンサー

+5

素朴な疑問なのですが、なぜ、一番上の部分から取得しようとしたのでしょうか。

MySQLの気まぐれです。何が取られるかは、全く保証されません。

サーバーは各グループから任意の値を自由に選択できるため、同じ値でなければ、選択した値は不確定です(MySQL 5.6 リファレンスより)。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+3

DB では通常、明示的に order by しない限り、結果の並び順は不定です。

ただ、実際の動作として捉えた場合、取得時に利用したインデックスの順に並んでいることが予想されます。
フルスキャンになる場合はレコード群の先頭から順に処理しているでしょうから、その場合はレコードが登録された順番になることが予想されます。
※update が delete->insert の順で行われるような DB の場合、順番が変わる可能性もあります

そして、その結果を集計する場合の動作を考えると、まず得られた結果をソートしているとしても、ソート前の順序を壊さないソート(安定ソート)を使っているかどうかで結果が変わります。概ね安定ソートを使っているとは思うのですが、その辺は RDBMS 固有のアルゴリズムの部分なのでうかがい知れるものではありません。

以上のような理由で、たまたまその順番になったに過ぎません。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+3

仕様については、maisumakun さんが書かれている通りです。

補足をしておくと、
select bang,max(uria),tuki from tb;
という SQL 文は、使用方法的に誤りであるということです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+3

そもそもgroup byしないでmaxを取る場合はそのカラムだけしか拾えません

select max(uria) from tb;


他のカラムを一緒に拾うのは本来であれば文法エラーです

select bang,max(uria),tuki from tb;


MySQLのバージョンによってはエラーにならないこともありますが
それは「しょうがないからなにか適当な(いい加減な)データを表示してやるか」
というMySQLの優しさでしかありません。

それはたとえば

select bang,max(uria),min(uria),tuki from tb;


としたとき、bangやtukiは最大値のものを取るのか最小値のものをとるのかわからないですよね?
つまりなにか適当なものをとってくるのです。

なお一般に最大値のデータをとるにはこうします

select * from tb as t1 where not exists(select 1 from tb where uria>t1.uria);

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+3

まず、 maxを使ったときに、他のカラムが取得できる動作は、最近のMySQLではデフォルトでオフになっているはず。参考資料、環境を見直されることをおすすめします。

で、私の回答なんですが、

  • なぜ一番上から取ったと言えるのでしょうか?

というレコードが取得できます。
カラムbangとtukiの値は、tbテーブルの一番上の部分

と書いておられる部分なんですが、私には、bangは最初の表で言う9番目の、tukiは4番目の値が取られているように見えて仕方がありません。なぜ一番上を取ったと言えるのでしょうか?たしかにbangを9番目の、tukiを4番目のレコードから取ったというのは、両方を1番目から取ったと考えるより変です。ただ、この明らかに変な主張を否定できないのが、他の方も仰っておられる"不定"であるということだと思います。

  • 一番目が取られるのは当然
    最初の表を出したクエリもorder byされていません。つまり、最初の表の順序が本来的に不定なはずです。このとき、"仕様上は不定である"といっても使っているデータベースはどこかには実装が存在するのですから、取りやすい、取りにくいがあるはずです。つまり、最初の表は、現に存在するあなたのデータベースで、結果として取得しやすかったり、表示しやすかった順で表示されている、と考えられます。
    であれば、また別のクエリをしたとき、制約のかかっていないデータが、最も取得・表示しやすい第一のレコードになっているのは、必然ではないでしょうか。逆に、指定もしていないのに、全テーブルから取得した後ろから30%の位置にある行が取得できるほうが、どういう仕組みがあるんだろう、と悩むべきことに思えます。

RDBは設計として集合の操作です。集合それ自身には順序性がありません。結果として上から並んでいることを暗黙に順序がある(一番目とか二番目とか)と認識するのは誤解のもとでしかないです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/17 21:09

    MySQL 8.0ではデフォルトで取れなくなっていたようです。ありがとうございます。

    https://dev.mysql.com/doc/refman/8.0/en/group-by-handling.html

    キャンセル

+2

素朴な疑問なのですが、なぜ、一番上の部分から取得しようとしたのでしょうか。仕様と言われるとそれまでですが、何か理由があるのでしょうか。

内容的には他の方と重複してしまいますが、標準SQLでは不正となるMySQLの独自拡張仕様です。
12.19.3 MySQL での GROUP BY の処理
ONLY_FULL_GROUP_BY を有効にすると、この MySQL拡張が無効になりますので、設定されてはどうでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

仕様と言われるとそれまでですが、何か理由があるのでしょうか。 

重箱の隅をつつくようで申し訳ないですが、
「仕様」はそもそもが「理由」が含まれているものです。
なので「仕様」ということでそれまでにされては?

技術者として興味・探求心があるのは結構なことなのですが、
自身が作ったものでなければ深く追ったところで利用者がどうにかできるわけでもなく、
既に回答が出ているように、確実に保証されているものではないので、
そのような仕様であると理解した上で、
気にしなくて済むようにorder byは何であっても入れるように習慣づけるまたは
必ずorder byを入れて取得するような設計をするだけかと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.58%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る