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

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

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Q&A

解決済

3回答

6286閲覧

なぜgroup byができないか

退会済みユーザー

退会済みユーザー

総合スコア0

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

0グッド

1クリップ

投稿2017/11/24 10:14

編集2017/11/24 10:30

基礎からのmysqlを読んでいます。
tb1でtosiの大きいものからの順位をつけるのが目的です。

tb1 +------+--------+------+ | bang | nama | tosi | +------+--------+------+ | A101 | 佐藤 | 40 | | A102 | 高橋 | 28 | | A103 | 中川 | 20 | | A104 | 渡辺 | 23 | | A105 | 西沢 | 35 | +------+--------+------+
select a.nama,a.tosi,count(*) from tb1 as a join tb1 as b where a.tosi <= b.tosi group by a.bang;

と本に記載通り入力したところ

Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'db1.a.nama' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

と言うエラーが出てきてしまいます。翻訳を見てもなぜエラーになるのかがわかりません。
これは何が原因でコードをどうすればいいのでしょうか?また#1とはどういう意味なのでしょうか?
それとcount(*)で表示される数字がそのまま順位になるとの記載があったのですがa.tosi <= b.tosiだと逆になってしまうのではないのでしょうか?

a +------+--------+------+ | bang | nama | tosi | +------+--------+------+ | A101 | 佐藤 | 40 | | A102 | 高橋 | 28 | | A103 | 中川 | 20 | | A104 | 渡辺 | 23 | | A105 | 西沢 | 35 | +------+--------+------+ b +------+--------+------+ | bang | nama | tosi | +------+--------+------+ | A105 | 西沢 | 35 | | A105 | 西沢 | 35 | | A105 | 西沢 | 35 | | A105 | 西沢 | 35| | A105 | 西沢 | 35 | +------+--------+------+

西沢の例ですと、となるのでa.tosi <= b.tosiだとcountは4になり、順位が2にならないきがするのですが。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/11/24 10:44

MySQLのバージョンは5.7以上ではありませんか?
退会済みユーザー

退会済みユーザー

2017/11/24 10:48

5.7だと仕様がかわったのでしょうか?
退会済みユーザー

退会済みユーザー

2017/11/25 10:20

GROUP BYの可能な条件が厳密になりました。
退会済みユーザー

退会済みユーザー

2017/11/25 13:35

以前はこの命令文でもエラーにはならなかったのでしょうか?
退会済みユーザー

退会済みユーザー

2017/11/25 13:41

「MySQLのバージョンは5.7以上ではありませんか? 」の質問の答えは?
退会済みユーザー

退会済みユーザー

2017/11/25 13:45

バージョンは5.7.20を使っています
guest

回答3

0

group by 句に含まれていないカラムは、集計関数と一緒に指定しないといけません。

参考
http://su-kun1899.hatenablog.com/entry/2016/06/15/230000

投稿2017/11/25 13:50

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/11/25 13:56

only_full_group_byが5.7から有効になったのですね 知らなかったです
sazi

2017/11/25 14:58

成程。 5.7より前に書かれた記事ならそのバージョンのmysqlではエラーにはならないってことですね。 それにしても、mysqlの緩さに甘えた記述を本に使うというのもどうかと思いますけれど。
guest

0

ベストアンサー

エラーをgoogle翻訳してみました。

SELECTリストの式#1はGROUP BY句にはなく、GROUP BY句のカラムに機能的に依存しない非集約カラム db1.a.namaを含みます。 これはsql_mode = only_full_group_byと互換性がありません

group by 句を指定した時には、select する項目はgroup byで指定されなければなりません。
select で指定している a.nama,a.tosiがgroup byで指定されていないからエラーなのです。
誤植には見えないので、こんな基本的なところが間違っている市販本は在り得ません。

多分、以下のような記述ではないでしょうか(joinは直積で表現)

SQL

1select a.bang,a.nama,a.tosi,count(*) from tb1 as a , tb1 as b where a.tosi <= b.tosi group by a.bang,a.nama,a.tosi;

tb1でtosiの大きいものからの順位をつけるのが目的です。

西沢の例ですと、となるのでa.tosi <= b.tosiだとcountは4

にはならないですね。
表示するのはa.tosiですから、それ以上のというのは35と45の2件です。

コメントに対しての説明で追記

(bang,nama)=(A105,西沢)の例で説明します。
where条件が無いとき

a.banga.namaa.tosib.bangb.namab.tosi
A105西沢35A101佐藤40
A105西沢35A102高橋28
A105西沢35A103中川20
A105西沢35A104渡辺23
A105西沢35A105西沢35

where条件 a.tosi <= b.tosi のとき

a.banga.namaa.tosib.bangb.namab.tosi
A105西沢35A101佐藤40
A105西沢35A105西沢35

上記をaの項目でgroup by すると count(*)は2となる
※group by するときは、group by の無い状態で確認すると分かり易いですよ。

投稿2017/11/24 15:17

編集2017/11/25 02:49
sazi

総合スコア25173

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/11/24 15:55

>group by 句を指定した時には、select する項目はgroup byで指定されなければなりません こういう明確なルールを教えていただけるとわかりやすくて助かります 基礎からのmysqlは有名で評価も高かったので買ってみたのですが基本が間違っているんですね・・・ select * from tb group by bang;のような記述の場所もありやはりgroup byに含まれていないカラムがselectにあるためエラーが出てきました。
退会済みユーザー

退会済みユーザー

2017/11/24 15:58

>表示するのはa.tosiですから、それ以上のというのは35と45の2件です。 aのtosiは40,28,20,23,35でbのtosiは35なのでa.tosi <= b.tosiに当てはまるものは20,23,28,35になるのではないのでしょうか?
sazi

2017/11/24 16:05

a.tosiを基準にカウントしているので逆です
退会済みユーザー

退会済みユーザー

2017/11/24 16:26

すいませんよくわからないです a.tosi <= b.tosiでなぜa.tosiが基準になるのでしょうか? <=を見る限りaのテーブルにある年齢よりも大きいbの年齢はどれかと言う意味になるのではないのでしょうか?
sazi

2017/11/25 02:41

追記しました。(SQLのfrom句での結合の表現が元々でjoinしかなかったので変更) でも、試せば少なくとも結果は分かるはずです。 理解を進める上でも、手は動かしましょう。
退会済みユーザー

退会済みユーザー

2017/11/25 04:11 編集

図表の通りであればわかるのですが、select * from tb1 as a join tb1 as b;だとa.bang a.nama a.tosiが佐藤高橋中川渡辺西沢でb.bang b.nama b.tosiが西沢*5になるのではないでしょうか? 実際mysqlモニタにコードを打ってもそうなるのですが。
sazi

2017/11/25 04:16

表示がそうなっているだけで、逆の組み合わせもあるはずですよ。 order byをa項目に指定して並び変えをしてみてください
退会済みユーザー

退会済みユーザー

2017/11/25 04:31

aで並び替えをすればa.bang a.nama a.tosi西沢*5には確かになるのですが、where a.tosi <= b.tosiはaを基準に並び替えたら成立する式ということになるんですよね。 それはgroup by a.nama,a.tosiでaを基準にしているからと言うことなのでしょうか?
sazi

2017/11/25 04:36 編集

a.tosi <= b.tosiに並びは関係ないです。 総当たりでできた行の中での値の比較です。 group byはカウントを取るのが目的で、whereの条件はgroup byを実行する前に処理されます。
sazi

2017/11/25 04:38

多分、a.tosi <= b.tositという条件が他の行に作用しているイメージを持っているので誤解してます。 from 句で取得できた結果の表の1行についての条件なのです。
退会済みユーザー

退会済みユーザー

2017/11/25 05:20 編集

select * from tb1 as a join tb1 as b; +------+--------+------+------+--------+------+ | bang | nama | tosi | bang | nama | tosi | +------+--------+------+------+--------+------+ | A101 | 佐藤 | 40 | A101 | 佐藤 | 40 | | A102 | 高橋 | 28 | A101 | 佐藤 | 40 | | A103 | 中川 | 20 | A101 | 佐藤 | 40 | | A104 | 渡辺 | 23 | A101 | 佐藤 | 40 | | A105 | 西沢 | 35 | A101 | 佐藤 | 40 | | A101 | 佐藤 | 40 | A102 | 高橋 | 28 | | A102 | 高橋 | 28 | A102 | 高橋 | 28 | | A103 | 中川 | 20 | A102 | 高橋 | 28 | | A104 | 渡辺 | 23 | A102 | 高橋 | 28 | | A105 | 西沢 | 35 | A102 | 高橋 | 28 | | A101 | 佐藤 | 40 | A103 | 中川 | 20 | | A102 | 高橋 | 28 | A103 | 中川 | 20 | | A103 | 中川 | 20 | A103 | 中川 | 20 | | A104 | 渡辺 | 23 | A103 | 中川 | 20 | | A105 | 西沢 | 35 | A103 | 中川 | 20 | | A101 | 佐藤 | 40 | A104 | 渡辺 | 23 | | A102 | 高橋 | 28 | A104 | 渡辺 | 23 | | A103 | 中川 | 20 | A104 | 渡辺 | 23 | | A104 | 渡辺 | 23 | A104 | 渡辺 | 23 | | A105 | 西沢 | 35 | A104 | 渡辺 | 23 | | A101 | 佐藤 | 40 | A105 | 西沢 | 35 | | A102 | 高橋 | 28 | A105 | 西沢 | 35 | | A103 | 中川 | 20 | A105 | 西沢 | 35 | | A104 | 渡辺 | 23 | A105 | 西沢 | 35 | | A105 | 西沢 | 35 | A105 | 西沢 | 35 | +------+--------+------+------+--------+------+ 総当たりだとこうなって左がa右がbになるんですよね? それでa.tosi <= b.tosiをした場合、左の佐藤基準だと左の佐藤のtosiよりも大きいbは1つだけ、右の佐藤基準だと右の佐藤のtosiよりも小さいaは5つになるのですがaが基準になるというのはどこで判断されているのでしょうか?
sazi

2017/11/25 10:13 編集

この結果にa.tosi <= b.tosiの条件を与えるとaもbも佐藤の行が1行になりますよね。 aを基準にしたいから、a.tosi <= b.tosiという条件を与えているので当然aの項目でgroup byです。 それをカウントするから1件ですね
sazi

2017/11/25 10:19

なぜ基準になるのか?ではなく >tb1でtosiの大きいものからの順位をつけるのが目的です。 の為に、そういう記述になるのですけど。
sazi

2017/11/25 10:23

試しにwhere条件をa.tosi >= b.tosiのように逆にすると「小さいもの順」になりますので、どちらが基準になるかを勝手に判断しているわけではないですよ。
退会済みユーザー

退会済みユーザー

2017/11/25 13:44

>この結果にa.tosi <= b.tosiの条件を与えるとaもbも佐藤の行が1行になりますよね。 | A101 | 佐藤 | 40 | A101 | 佐藤 | 40 | | A102 | 高橋 | 28 | A101 | 佐藤 | 40 | | A103 | 中川 | 20 | A101 | 佐藤 | 40 | | A104 | 渡辺 | 23 | A101 | 佐藤 | 40 | | A105 | 西沢 | 35 | A101 | 佐藤 | 40 | これは全部a.tosi <= b.tosiを満たしているのですが佐藤の行はbの方は5行あるのではないでしょうか? >aを基準にしたいから、a.tosi <= b.tosi b.tosi >= a.tosiも条件は同じなのですがこれも同じようにaが基準になるのでしょうか?
sazi

2017/11/25 14:44

>これは全部a.tosi <= b.tosiを満たしているのですが佐藤の行はbの方は5行あるのではないでしょうか? そうですが、aを基準にしたときは1行です。 Aを軸にしての考えに対して、逆の表にしているから混乱しているのではないですか? >b.tosi >= a.tosiも条件は同じなのですがこれも同じようにaが基準になるのでしょうか? そうです。辺の入れ替えしても同じです。 命題に対して、直積と条件と集計を組み合わせて結果を出そうとしてこのSQLがあるわけです。 記述してあるSQLから見るとaを基準(軸)にしているということです。
sazi

2017/11/25 14:48

別な見方をするために、佐藤さんの結果を取り出すためにwhereに条件を追加してみて下さい。 a、bどちらの項目を指定することになりますか?
退会済みユーザー

退会済みユーザー

2017/11/25 14:53

>記述してあるSQLから見るとaを基準(軸)にしているということです。 何度も回答をして頂いてありがとうございます。左側を基準とした場合佐藤が1行になりcountも順位も1になることはわかりました。ただaが基準になるというのはどこで判断がされているのでしょうか?sqlでfrom tb1 as aとなっている方が基準でjoin tb1 as bされている方が基準に付随するものになるという判断なのでしょうか?
sazi

2017/11/25 15:05

>ただaが基準になるというのはどこで判断がされているのでしょうか? どう処理されているかは、group by で指定されている事からです。 select でcount(*)だけにしても結果は変わりませんので。(表示は当然変わるけど) joinを使用して記述されている場合は、最初に記述されているものが駆動表であることが多いですけど、書き方でどうにでもなりますから、SQL全体をみないと分かりませんけどね。
退会済みユーザー

退会済みユーザー

2017/11/25 16:39

groupで基準が決まっていたんですね。 selectからaとbの記述をなくしてcountだけにしてみてやってみたらgroupの書き方で結果が変わりました。 長々と回答をしていただいてありがとうございました。助かりました。
guest

0

もしその参考書にご提示のSQLが本当に記載されているならその書籍は捨てたほうがいいでしょう

ランクのつけかたはこうです

SQL

1select nama,tosi 2,(select count(*) from tb1 as b where a.tosi <= b.tosi) rank 3from tb1 as a 4order by rank asc 5

投稿2017/11/24 12:33

yambejp

総合スコア114769

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/11/24 14:49 編集

ご回答ありがとうございます。 rankを使えばそういう書き方になるみたいなのですが、自己結合をしてaとbの数をcountで数えて順位をつける場合はどういう書き方にすればいいのでしょうか? select a.nama,a.tosi,count(*) from tb1 as a join tb1 as b where a.tosi <= b.tosi group by a.bang; の原型を変えずに修正したsql文にしたいです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問