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

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

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

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

Q&A

解決済

3回答

772閲覧

サブクエリでおおもとのクエリのエイリアスを使った時のエラーを説明して下さい。

snowshink

総合スコア138

MySQL

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

0グッド

0クリップ

投稿2019/04/26 01:29

編集2019/04/28 22:23

sql

1select teamName , positionName ,uniformNo ,playerName 2from player p 3join team using(teamNo) 4join position1 using(PositionNo) 5where positionNo = 6( 7 select positionNo 8from player 9where p.teamNo = 2 and p.uniformNo=5 10);

上記のクエリを実行すると、サブクエリの結果が2つ以上ありますとでました。

そこで、5行目の=をinに変えたところ結果はサブクエリでの条件がおおもとのクエリの条件になった場合(下のコード)と一致しました。

内部でどのような処理が行われて、サブクエリでどのようなテーブルが呼び出されたのでしょうか。

自分の予想では、サブクエリで呼び出されたテーブルはplayerそのものとおおもとのクエリでjoinしたplayerテーブルを下のwhere句で絞ったものが
呼び出されて、playerテーブルにはteamNameとpositionNameのカラムがないのでjoinされたテーブルのみ該当してinにしたとき、playerテーブルのみと一致したものは除外されたと考えたのですが、そうするとinにしたときの結果が1件なのが説明できません。

sql

1select teamName , positionName ,uniformNo ,playerName 2from player p 3join team using(teamNo) 4join position1 using(PositionNo) 5where p.teamNo = 2 and p.uniformNo=5;

playerにはteamNo,positionNo,uniformNo,playerName 、
teamには teamNo , teamName 、
position1には positionNo, positionName のカラムがあります。

追記

SQL

1CREATE TABLE Position1( 2 SportNo VARCHAR(2) NOT NULL, 3 PositionNo VARCHAR(2) NOT NULL, 4 PositionName VARCHAR(20) NOT NULL, 5 PRIMARY KEY(SportNo,PositionNo)) CHARSET=SJIS; 6CREATE TABLE Player( 7 TeamNo VARCHAR(2) NOT NULL, 8 PositionNo VARCHAR(2) NOT NULL, 9 UniformNo VARCHAR(2) NOT NULL, 10 BirthDay DATE NOT NULL, 11 PlayerName VARCHAR(20) NOT NULL, 12 PRIMARY KEY(TeamNo,UniformNo)) CHARSET=SJIS; 13CREATE TABLE Team( 14 SportNo VARCHAR(2) NOT NULL, 15 LeagueNo VARCHAR(2) NOT NULL, 16 AreaNo VARCHAR(2) NOT NULL, 17 TeamNo VARCHAR(2) NOT NULL, 18 TeamName VARCHAR(50) NOT NULL, 19 PRIMEKEY(TeamNo)) CHARSET=SJIS; 20

やろうとしたことはチーム番号2、背番号5の人と同じポジションの人のチーム名、ポジション名、背番号、選手名を取得することです。

ちなみにこれは演習として作ったクエリです。

皆さんの回答を見て、勘違いされているようなので追記します。
私が知りたいのは「このクエリ文で呼びされたサブクエリの中身」から「クエリ文が実行されたときの内部処理の内容」であって、
エラーの直しかたではないです。サブクエリ文のエイリアスをとればいいのは分かってます。

質問は

内部でどのような処理が行われて、サブクエリでどのようなテーブルが呼び出されたのでしょうか。

ですから。

このエラーの直し方を教えてください

ではないです。

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

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

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

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

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

Orlofsky

2019/04/26 01:33

テーブル定義はCREATE TABLEで提示しては?
Y.H.

2019/04/26 01:42

あと、どういうデータが入っていて、どういう結果が欲しいのかも質問に記載ください。
Y.H.

2019/04/26 01:59

Teamテーブルの主キーは何ですか?
Y.H.

2019/04/27 06:23

>このエラーの直し方を教えてください >ではないです。 であれば質問のタイトルを修正されることをお勧めします。
guest

回答3

0

そもそもやる意味のないSQLなので挙動を確認する意味があまり感じられませんが
具体的にどうやって判断されているかを確認したいなら
もしphpMyAdminを導入していれば、explainをかけて
クエリ結果操作欄に表示されるオプティマイズされたSQL文を見比べてみるとよいでしょう

投稿2019/04/26 02:32

yambejp

総合スコア114779

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

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

0

5行目の=をinに変えたところ結果はサブクエリでの条件がおおもとのクエリの条件になった場合(下のコード)と一致しました。

条件での=は単一の結果を期待するもので、inは集合です。

なので、サブクエリーでの結果が複数である場合、=だとエラーになります。
これはselectに記述するサブクエリーも=の結果を期待するので、同様にエラーになります。

そうするとinにしたときの結果が1件なのが説明できません。

サブクエリーで返却されるpositionNoの内容が1パターンしかないという単なる結果です。
サブクエリーにDISTINCT指定をすれば=にしてもエラーにはならないでしょう。

SQL

1where positionNo =( 2 select distinct positionNo 3 from player 4 where p.teamNo = 2 and p.uniformNo=5 5 )

但し、それはサブクエリーがpositionNoを1パターンしか返さない場合だけです。

追記

やろうとしたことはチーム番号2、背番号5の人と同じポジションの人のチーム名、ポジション名、背番号、選手名を取得することです。

それなら、サブクエリーが相関になっているのはおかしいです。
以下なら=でもエラーにならないと思います。

SQL

1select teamName , positionName ,uniformNo ,playerName 2from player p 3join team using(teamNo) 4join position1 using(PositionNo) 5where positionNo =( 6 select positionNo 7 from player 8 where teamNo = 2 and uniformNo=5 9 )

追記2

皆さんの回答を見て、勘違いされているようなので追記します。

「サブクエリでおおもとのクエリのエイリアスを使った時のエラーを説明して下さい。」
タイトルが、勘違いの元です。
そもそも、p.というのはエイリアスではなくて修飾子と言います。

内部でどのような処理が行われて、サブクエリでどのようなテーブルが呼び出されたのでしょうか。

サブクエリー内でfrom句に記述されたテーブル等を参照するものを、相関サブクエリー(相関副問合せ)と云います。

相関副問合せでは、参照される側(fromにある記述)が先実行されてから、参照する側が実行されます。
参照される側1件に対して都度実行されるのが基本です。
オプチマイザや内容によって事前に抽出が行われる事もあるでしょうし、どのような実行順序となっているかは、実行計画で確認する方が良いでしょう。

投稿2019/04/26 02:12

編集2019/04/29 02:02
sazi

総合スコア25173

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

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

0

ベストアンサー

追記

(コメントより)

仕組みを理解したくて質問させていただきました
inにした場合の結果が一件だけなのでしょうか

サブクエリーの結果は全件取得されています。

実行計画(実行プラン)を確認してみないと正確な事は判りませんが、以下と同等な実行がなされたのではないでしょうか?
※本質問のような疑問に対しては実行計画(実行プラン)を確認すると解ることが多いです。使用方法および結果の見方を覚えておかれると役立つと思います。(また、SQLの性能改善には利用必須の機能となります)

親のselect文のテーブルplayer pに対してサブクエリーのwhere p.teamNo = 2 and p.uniformNo=5(キー項目による絞り込み)が評価され1件が抽出ます。
このレコードがサブクエリー(結果:player全件)に存在するため、sql全体として1件抽出される結果となります。

( select teamName , positionName ,uniformNo ,playerName from player where teamNo = 2 and uniformNo=5 ) p join team using(teamNo) join position1 using(PositionNo) where positionNo in ( select positionNo from player );

saziさんの回答(追記2)にも記載されていますが、このようなMySQLの動作に関する事柄についてはMySQLのマニュアル「8.2.1.18.4 EXISTS 戦略によるサブクエリーの最適化」に記載されています。
この部分来限らず、MySQLについての動作原理について疑問を解消(または理解を深める)ならば、公式のマニュアルを読まれることをお勧めします。


このサブクエリーですが、Playerとの結合がないのでplayerテーブルの全件が取得されます。

select positionNo from player where p.teamNo = 2 and p.uniformNo=5

具体的なテーブル定義とデータの提示がないので何がやりたいのかわかりませんが、以下ではないでしょうか?

select positionNo from player where player.teamNo = 2 and player.uniformNo = 5

投稿2019/04/26 01:38

編集2019/05/01 00:20
Y.H.

総合スコア7914

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

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

snowshink

2019/04/26 01:54

はい、そのクエリで実行したら確かに実行されました。 今回はエラーから仕組みを理解したくて質問させていただきました。
Y.H.

2019/04/26 02:10

> where p.teamNo = 2 and p.uniformNo=5 だと、サブクエリー内でselect しているPlayerテーブルのteamNo, uniformNoに対して条件を与えていないので、サブクエリー内は(select positionNo from player)としてのと同じです。 よって、2件以上のpositionNoがサブクエリーの結果となります。 よって親のselect分のwhere条件は以下となります。 where positionNo = (2件以上のpositionNo) ここで、= は、単一の値の比較を行う演算子であることはわかりますか? 右辺が(2件以上のpositionNo)となっているため「サブクエリの結果が2つ以上あります」のエラーとなります。 Whereの条件で回答記載のように、 > where Player.teamNo = 2 and Player.uniformNo=5 とすることで、サブクエリの結果が1件となり(データがわからないので結果として1件になっている可能性もある)=で比較可能となりました。
snowshink

2019/04/28 22:26

ではなぜ、inにした場合の結果が一件だけなのでしょうか。 解答から推測すると全件出てくるように思えるのですが
Y.H.

2019/05/05 18:23

回答に追記していますが、これでは回答になってませんでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問