MySQLのクエリの概要

前書き

データベースは、多くのWebサイトおよびアプリケーションの重要なコンポーネントであり、インターネット上でのデータの保存および交換の中心です。 データベース管理の最も重要な側面の1つは、アドホックベースであるか、アプリケーションにコーディングされたプロセスの一部であるかにかかわらず、データベースからデータを取得する方法です。 データベースから情報を取得する方法はいくつかありますが、最も一般的に使用される方法の1つは、コマンドラインから_queries_を送信することで実行されます。

リレーショナルデータベース管理システムでは、_query_はテーブルからデータを取得するために使用されるコマンドです。 構造化クエリ言語(SQL)では、ほとんどの場合、クエリは `+ SELECT +`ステートメントを使用して作成されます。

このガイドでは、SQLクエリの基本的な構文と、より一般的に使用されるいくつかの関数と演算子について説明します。 また、MySQLデータベースのサンプルデータを使用してSQLクエリを作成する練習も行います。

MySQLは、オープンソースのリレーショナルデータベース管理システムです。 最も広く導入されているSQLデータベースの1つであるMySQLは、速度、信頼性、および使いやすさを優先します。 MySQLは一般にANSI SQL標準に従いますが、MySQLが認識された標準とは異なる方法で操作を実行する場合がいくつかあります。

前提条件

一般に、このガイドに記載されているコマンドと概念は、SQLデータベースソフトウェアを実行しているLinuxベースのオペレーティングシステムで使用できます。 ただし、MySQLを実行するUbuntu 18.04サーバーを念頭に置いて作成されています。 これを設定するには、次のものが必要です。

  • sudo特権を持つ非rootユーザーを持つUbuntu 18.04マシン。 これは、https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-18-04 [Ubuntu 18.04の初期サーバーセットアップガイド]を使用して設定できます。

  • マシンにインストールされたMySQL。 Ubuntu 18.04にMySQLをインストールする方法のガイドは、この設定に役立ちます。

このセットアップが完了したら、チュートリアルを開始できます。

サンプルデータベースの作成

SQLでクエリを作成する前に、まずデータベースといくつかのテーブルを作成してから、これらのテーブルにサンプルデータを入力します。 これにより、後でクエリを作成し始めるときに、実際の経験を積むことができます。

このガイド全体で使用するサンプルデータベースについて、次のシナリオを想像してください。

_あなたとあなたの友人の何人かは皆、お互いに誕生日を祝います。 毎回、グループのメンバーは地元のボーリング場に向かい、友好的なトーナメントに参加します。その後、全員があなたの場所に向かい、誕生日の人のお気に入りの食事を準備します。

_この伝統がしばらく続いているので、これらのトーナメントの記録の追跡を開始することにしました。 また、夕食の計画を簡単にするために、友人の誕生日とお気に入りのメインディッシュ、サイド、デザートの記録を作成することにします。 この情報を物理的な台帳に保存するのではなく、MySQLデータベースに記録することでデータベーススキルを行使することにします。

まず、* root * MySQLユーザーとしてMySQLプロンプトを開きます。

sudo mysql

次に、次を実行してデータベースを作成します。

CREATE DATABASE `birthdays`;

次に、次のように入力してこのデータベースを選択します。

USE birthdays;

次に、このデータベース内に2つのテーブルを作成します。 最初のテーブルを使用して、ボーリング場での友人の記録を追跡します。 次のコマンドは、各友人の「+ name 」、勝ったトーナメントの数(「 wins 」)、常に「 best 」スコアの列を持つ「 tourneys 」というテーブルを作成します、および着用するボウリングシューズのサイズ( ` size +`):

CREATE TABLE tourneys (
name varchar(30),
wins real,
best real,
size real
);

「+ CREATE TABLE」コマンドを実行し、列見出しを入力すると、次の出力が表示されます。

OutputQuery OK, 0 rows affected (0.00 sec)

`+ tourneys +`テーブルにサンプルデータを入力します。

INSERT INTO tourneys (name, wins, best, size)
VALUES ('Dolly', '7', '245', '8.5'),
('Etta', '4', '283', '9'),
('Irma', '9', '266', '7'),
('Barbara', '2', '197', '7.5'),
('Gladys', '13', '273', '8');

次のような出力が表示されます。

OutputQuery OK, 5 rows affected (0.01 sec)
Records: 5  Duplicates: 0  Warnings: 0

この後、同じデータベース内に別のテーブルを作成します。このテーブルは、友人のお気に入りの誕生日の食事に関する情報を保存するために使用します。 次のコマンドは、各友人の「+ name 」、「 birthdate 」、お気に入りの「 entree 」、お気に入りの「 side 」料理、およびお気に入りの「 +デザート `:

CREATE TABLE dinners (
name varchar(30),
birthdate date,
entree varchar(30),
side varchar(30),
dessert varchar(30)
);

この表についても同様に、コマンドが正常に実行されたことを確認するフィードバックを受け取ります。

OutputQuery OK, 0 rows affected (0.01 sec)

このテーブルにいくつかのサンプルデータも入力します。

INSERT INTO dinners (name, birthdate, entree, side, dessert)
VALUES ('Dolly', '1946-01-19', 'steak', 'salad', 'cake'),
('Etta', '1938-01-25', 'chicken', 'fries', 'ice cream'),
('Irma', '1941-02-18', 'tofu', 'fries', 'cake'),
('Barbara', '1948-12-25', 'tofu', 'salad', 'ice cream'),
('Gladys', '1944-05-28', 'steak', 'fries', 'ice cream');
OutputQuery OK, 5 rows affected (0.00 sec)
Records: 5  Duplicates: 0  Warnings: 0

そのコマンドが正常に完了すると、データベースのセットアップは完了です。 次に、 `+ SELECT +`クエリの基本的なコマンド構造について説明します。

SELECTステートメントについて

はじめに述べたように、SQLクエリはほとんどの場合、 `+ SELECT `ステートメントで始まります。 ` SELECT `はクエリで使用され、テーブルのどの列が結果セットで返されるかを指定します。 クエリには、ほとんどの場合、「 FROM +」も含まれます。これは、ステートメントがクエリするテーブルを指定するために使用されます。

一般に、SQLクエリは次の構文に従います。

SELECT  FROM  WHERE ;

例として、次のステートメントは `+ dinners `テーブルから ` name +`カラム全体を返します:

SELECT name FROM dinners;
Output+---------+
| name    |
+---------+
| Dolly   |
| Etta    |
| Irma    |
| Barbara |
| Gladys  |
+---------+
5 rows in set (0.00 sec)

次のように、名前をカンマで区切ることにより、同じテーブルから複数の列を選択できます。

SELECT name, birthdate FROM dinners;
Output+---------+------------+
| name    | birthdate  |
+---------+------------+
| Dolly   | 1946-01-19 |
| Etta    | 1938-01-25 |
| Irma    | 1941-02-18 |
| Barbara | 1948-12-25 |
| Gladys  | 1944-05-28 |
+---------+------------+
5 rows in set (0.00 sec)

特定の列または列セットに名前を付ける代わりに、テーブル内のすべての列を表すプレースホルダーとして機能するアスタリスク( + * +)を付けて `+ SELECT `演算子に従うことができます。 次のコマンドは、 ` tourneys +`テーブルのすべての列を返します:

SELECT * FROM tourneys;
Output+---------+------+------+------+
| name    | wins | best | size |
+---------+------+------+------+
| Dolly   |    7 |  245 |  8.5 |
| Etta    |    4 |  283 |    9 |
| Irma    |    9 |  266 |    7 |
| Barbara |    2 |  197 |  7.5 |
| Gladys  |   13 |  273 |    8 |
+---------+------+------+------+
5 rows in set (0.00 sec)

`+ WHERE `は、指定された条件を満たすレコードをフィルタリングするクエリで使用され、その条件を満たさない行は結果から削除されます。 通常、 ` WHERE +`句は次の構文に従います。

. . . WHERE

`+ WHERE +`句の比較演算子は、指定された列を値と比較する方法を定義します。 一般的なSQL比較演算子を次に示します。

Operator What it does

=

tests for equality

!=

tests for inequality

<

tests for less-than

>

tests for greater-than

<=

tests for less-than or equal-to

>=

tests for greater-than or equal-to

BETWEEN

tests whether a value lies within a given range

IN

tests whether a row’s value is contained in a set of specified values

EXISTS

tests whether rows exist, given the specified conditions

LIKE

tests whether a value matches a specified string

IS NULL

tests for NULL values

IS NOT NULL

tests for all values other than NULL

たとえば、Irmaの靴のサイズを検索する場合、次のクエリを使用できます。

SELECT size FROM tourneys WHERE name = 'Irma';
Output+------+
| size |
+------+
|    7 |
+------+
1 row in set (0.00 sec)

SQLではワイルドカード文字を使用できますが、これらは + WHERE +`句で使用する場合に特に便利です。 パーセント記号( `+%+)はゼロ個以上の不明な文字を表し、アンダースコア( + _ +)は単一の不明な文字を表します。 これらは、テーブル内の特定のエントリを見つけようとしているが、そのエントリが正確に何であるかわからない場合に役立ちます。 たとえば、いくつかの友人のお気に入りのメインディッシュを忘れたが、この特定のメインディッシュが「t」で始まると確信しているとしましょう。次のクエリを実行すると、その名前を見つけることができます。

SELECT entree FROM dinners WHERE entree LIKE 't%';
Output+--------+
| entree |
+--------+
| tofu   |
| tofu   |
+--------+
2 rows in set (0.00 sec)

上記の出力に基づいて、忘れた前菜は「+ tofu +」であることがわかります。

比較的長い名前または読みにくい名前の列またはテーブルがあるデータベースを使用している場合があります。 これらの場合、 `+ AS `キーワードでエイリアスを作成することにより、これらの名前をより読みやすくすることができます。 「 AS +」で作成されたエイリアスは一時的なものであり、作成されたクエリの期間中のみ存在します。

SELECT name AS n, birthdate AS b, dessert AS d FROM dinners;
Output+---------+------------+-----------+
| n       | b          | d         |
+---------+------------+-----------+
| Dolly   | 1946-01-19 | cake      |
| Etta    | 1938-01-25 | ice cream |
| Irma    | 1941-02-18 | cake      |
| Barbara | 1948-12-25 | ice cream |
| Gladys  | 1944-05-28 | ice cream |
+---------+------------+-----------+
5 rows in set (0.00 sec)

ここでは、「+ name 」列を「 n 」、「 birthdate 」列を「 b 」、「 dessert 」列を「 d +」として表示するようにSQLに指示しました。

これまでに説明した例には、SQLクエリで頻繁に使用されるキーワードと句の一部が含まれています。 これらは基本的なクエリには役立ちますが、データに基づいて計算を実行したり、スカラー値(複数の異なる値のセットではなく単一の値)を導出しようとする場合には役立ちません。 これは、集約関数が作用する場所です。

集約関数

多くの場合、データを操作するとき、必ずしもデータ自体を表示する必要はありません。 むしろ、データについての情報が必要です。 SQL構文には、 `+ SELECT +`クエリを発行するだけでデータの計算を解釈または実行できる多くの関数が含まれています。 これらは_aggregate functions_と呼ばれます。

`+ COUNT +`関数は、特定の条件に一致する行の数をカウントして返します。 たとえば、友人の何人が誕生日の前菜に豆腐を好むかを知りたい場合、次のクエリを発行できます。

SELECT COUNT(entree) FROM dinners WHERE entree = 'tofu';
Output+---------------+
| COUNT(entree) |
+---------------+
|             2 |
+---------------+
1 row in set (0.00 sec)

`+ AVG +`関数は列の平均(平均)値を返します。 サンプルの表を使用すると、次のクエリを使用して友達の中で平均最高スコアを見つけることができます。

SELECT AVG(best) FROM tourneys;
Output+-----------+
| AVG(best) |
+-----------+
|     252.8 |
+-----------+
1 row in set (0.00 sec)

`+ SUM +`は、指定された列の合計を見つけるために使用されます。 たとえば、あなたとあなたの友人が何年もの間ボウリングしたゲームの数を確認したい場合、次のクエリを実行できます。

SELECT SUM(wins) FROM tourneys;
Output+-----------+
| SUM(wins) |
+-----------+
|        35 |
+-----------+
1 row in set (0.00 sec)

`+ AVG `および ` SUM `関数は、数値データで使用した場合にのみ正しく機能することに注意してください。 非数値データでそれらを使用しようとすると、使用しているRDBMSに応じて、エラーまたは単に「+0」が発生します。

SELECT SUM(entree) FROM dinners;
Output+-------------+
| SUM(entree) |
+-------------+
|           0 |
+-------------+
1 row in set, 5 warnings (0.00 sec)

`+ MIN +`は、指定された列内の最小値を見つけるために使用されます。 このクエリを使用して、これまでの全体的な最悪のボウリング記録が何であるかを確認できます(勝利数の観点から)。

SELECT MIN(wins) FROM tourneys;
Output+-----------+
| MIN(wins) |
+-----------+
|         2 |
+-----------+
1 row in set (0.00 sec)

同様に、「+ MAX +」は特定の列の最大の数値を見つけるために使用されます。 次のクエリは、最高の全体的なボウリング記録を示します。

SELECT MAX(wins) FROM tourneys;
Output+-----------+
| MAX(wins) |
+-----------+
|        13 |
+-----------+
1 row in set (0.00 sec)

「+ SUM」および「+ AVG」とは異なり、「+ MIN」および「+ MAX」関数は、数値とアルファベットの両方のデータ型に使用できます。 文字列値を含む列で実行すると、 `+ MIN +`関数は最初の値をアルファベット順に表示します:

SELECT MIN(name) FROM dinners;
Output+-----------+
| MIN(name) |
+-----------+
| Barbara   |
+-----------+
1 row in set (0.00 sec)

同様に、文字列値を含む列で実行すると、 `+ MAX +`関数は最後の値をアルファベット順に表示します:

SELECT MAX(name) FROM dinners;
Output+-----------+
| MAX(name) |
+-----------+
| Irma      |
+-----------+
1 row in set (0.00 sec)

集計関数には、このセクションで説明した以外にも多くの用途があります。 これらは、結果セットのソート方法に影響を与える他のいくつかのクエリ句とともに次のセクションで説明する「+ GROUP BY +」句とともに使用すると特に役立ちます。

クエリ出力の操作

+ FROM`と + WHERE`句に加えて、 `+ SELECT +`クエリの結果を操作するために使用されるいくつかの他の句があります。 このセクションでは、より一般的に使用されるいくつかのクエリ句の例を説明し、例を提供します。

+ FROM`と + WHERE`を除き、最も頻繁に使用されるクエリ句の1つは `+ GROUP BY`句です。 通常、1つの列で集計関数を実行するときに、別の列の値の一致に関連して使用されます。

たとえば、作成した3つのメインディッシュのそれぞれを好む友人の数を知りたいとします。 この情報は、次のクエリで見つけることができます。

SELECT COUNT(name), entree FROM dinners GROUP BY entree;
Output+-------------+---------+
| COUNT(name) | entree  |
+-------------+---------+
|           1 | chicken |
|           2 | steak   |
|           2 | tofu    |
+-------------+---------+
3 rows in set (0.00 sec)

`+ ORDER BY`句はクエリ結果をソートするために使用されます。 デフォルトでは、数値は昇順でソートされ、テキスト値はアルファベット順にソートされます。 説明のために、次のクエリは `+ name `と ` birthdate +`カラムをリストしますが、結果を生年月日でソートします:

SELECT name, birthdate FROM dinners ORDER BY birthdate;
Output+---------+------------+
| name    | birthdate  |
+---------+------------+
| Etta    | 1938-01-25 |
| Irma    | 1941-02-18 |
| Gladys  | 1944-05-28 |
| Dolly   | 1946-01-19 |
| Barbara | 1948-12-25 |
+---------+------------+
5 rows in set (0.00 sec)

`+ ORDER BY `のデフォルトの動作は、結果セットを昇順でソートすることに注意してください。 これを逆にして、結果セットを降順にソートするには、 ` DESC +`でクエリを閉じます:

SELECT name, birthdate FROM dinners ORDER BY birthdate DESC;
Output+---------+------------+
| name    | birthdate  |
+---------+------------+
| Barbara | 1948-12-25 |
| Dolly   | 1946-01-19 |
| Gladys  | 1944-05-28 |
| Irma    | 1941-02-18 |
| Etta    | 1938-01-25 |
+---------+------------+
5 rows in set (0.00 sec)

前述のように、特定の条件に基づいて結果をフィルタリングするには、「+ WHERE 」句を使用します。 ただし、集計関数で ` WHERE +`句を使用すると、少なくとも3人の友人のお気に入りの側を見つける次の試行の場合と同様に、エラーが返されます。

SELECT COUNT(name), side FROM dinners WHERE COUNT(name) >= 3;
OutputERROR 1111 (HY000): Invalid use of group function

+ HAVING +`句がSQLに追加され、 `+ WHERE +`句と同様の機能を提供すると同時に、集計関数とも互換性があります。 これらの2つの句の違いを考えると、「+ WHERE +」は個々のレコードに適用され、「+ HAVING +」はグループレコードに適用されます。 このため、 `+ HAVING`句を発行するときはいつでも、 + GROUP BY`句も存在する必要があります。

次の例は、どのおかずが少なくとも3人の友人のお気に入りかを見つける別の試みです。ただし、これはエラーなしで結果を返します。

SELECT COUNT(name), side FROM dinners GROUP BY side HAVING COUNT(name) >= 3;
Output+-------------+-------+
| COUNT(name) | side  |
+-------------+-------+
|           3 | fries |
+-------------+-------+
1 row in set (0.00 sec)

集計関数は、特定のテーブルの特定の列の結果を要約するのに役立ちます。 ただし、複数のテーブルのコンテンツを照会する必要がある場合が多くあります。 次のセクションでこれを行ういくつかの方法について説明します。

複数のテーブルのクエリ

多くの場合、データベースには複数のテーブルが含まれており、それぞれが異なるデータセットを保持しています。 SQLは、複数のテーブルで単一のクエリを実行するためのいくつかの異なる方法を提供します。

`+ JOIN +`句を使用して、クエリ結果の2つ以上のテーブルの行を結合できます。 これは、テーブル間の関連列を見つけることによってこれを行い、出力で結果を適切にソートします。

`+ JOIN `句を含む ` SELECT +`ステートメントは通常、次の構文に従います。

SELECT ., .
FROM
JOIN  ON .=.;

`+ JOIN +`句は複数のテーブルの内容を比較するため、前の例では、列名の前にテーブル名とピリオドを付けて、各列を選択するテーブルを指定しています。 前のセクションで行ったように、単一のテーブルから選択する場合は必要ありませんが、クエリの場合、このように列を選択するテーブルを指定できます。 サンプルデータを使用して例を見てみましょう。

誕生日プレゼントとして、お友達のそれぞれにボウリングシューズを購入したいと想像してください。 友人の生年月日と靴のサイズに関する情報は別々のテーブルに保持されているため、両方のテーブルを個別に照会して、それぞれの結果を比較できます。 ただし、 `+ JOIN +`句を使用すると、1つのクエリで必要な情報をすべて検索できます。

SELECT tourneys.name, tourneys.size, dinners.birthdate
FROM tourneys
JOIN dinners ON tourneys.name=dinners.name;
Output+---------+------+------------+
| name    | size | birthdate  |
+---------+------+------------+
| Dolly   |  8.5 | 1946-01-19 |
| Etta    |    9 | 1938-01-25 |
| Irma    |    7 | 1941-02-18 |
| Barbara |  7.5 | 1948-12-25 |
| Gladys  |    8 | 1944-05-28 |
+---------+------+------------+
5 rows in set (0.00 sec)

この例で他の引数なしで使用される + JOIN`句は、内部の + JOIN`句です。 つまり、両方のテーブルで一致する値を持つすべてのレコードを選択して結果セットに出力し、一致しないレコードは除外されます。 この考えを説明するために、もう一方に対応するエントリがない各テーブルに新しい行を追加しましょう。

INSERT INTO tourneys (name, wins, best, size)
VALUES ('Bettye', '0', '193', '9');
INSERT INTO dinners (name, birthdate, entree, side, dessert)
VALUES ('Lesley', '1946-05-02', 'steak', 'salad', 'ice cream');

次に、 `+ JOIN `句を使用して前の ` SELECT +`ステートメントを再実行します。

SELECT tourneys.name, tourneys.size, dinners.birthdate
FROM tourneys
JOIN dinners ON tourneys.name=dinners.name;
Output+---------+------+------------+
| name    | size | birthdate  |
+---------+------+------------+
| Dolly   |  8.5 | 1946-01-19 |
| Etta    |    9 | 1938-01-25 |
| Irma    |    7 | 1941-02-18 |
| Barbara |  7.5 | 1948-12-25 |
| Gladys  |    8 | 1944-05-28 |
+---------+------+------------+
5 rows in set (0.00 sec)

`+ tourneys `テーブルにはLesleyのエントリがなく、 ` dinners +`テーブルにはBettyeのエントリがないため、これらのレコードはこの出力には存在しません。

ただし、outer `+ JOIN `句を使用して、テーブルの1つからすべてのレコードを返すことは可能です。 MySQLでは、 ` JOIN `句は ` LEFT JOIN `または ` RIGHT JOIN +`として記述されます。

`+ LEFT JOIN `句は、「左」テーブルのすべてのレコードと、右テーブルの一致するレコードのみを返します。 外部結合のコンテキストでは、左のテーブルは ` FROM `句によって参照されるテーブルであり、右のテーブルは ` JOIN +`ステートメントの後に参照される他のテーブルです。

前のクエリを再度実行しますが、今回は `+ LEFT JOIN +`句を使用します:

SELECT tourneys.name, tourneys.size, dinners.birthdate
FROM tourneys
LEFT JOIN dinners ON tourneys.name=dinners.name;

このコマンドは、右側のテーブルに対応するレコードがない場合でも、左側のテーブル(この場合は「+ tourneys 」)からすべてのレコードを返します。 右側のテーブルに一致するレコードがない場合は、RDBMSに応じて、「 NULL +」または単なる空白値として返されます。

Output+---------+------+------------+
| name    | size | birthdate  |
+---------+------+------------+
| Dolly   |  8.5 | 1946-01-19 |
| Etta    |    9 | 1938-01-25 |
| Irma    |    7 | 1941-02-18 |
| Barbara |  7.5 | 1948-12-25 |
| Gladys  |    8 | 1944-05-28 |
| Bettye  |    9 | NULL       |
+---------+------+------------+
6 rows in set (0.00 sec)

次に、今度は `+ RIGHT JOIN +`句を使用してクエリを再度実行します。

SELECT tourneys.name, tourneys.size, dinners.birthdate
FROM tourneys
RIGHT JOIN dinners ON tourneys.name=dinners.name;

これにより、右側のテーブル( + dinners +)からすべてのレコードが返されます。 レスリーの生年月日は右のテーブルに記録されているが、左のテーブルには彼女に対応する行がないため、「+ name 」列と「 size 」列はその行の「 NULL +」値として返されます。

Output+---------+------+------------+
| name    | size | birthdate  |
+---------+------+------------+
| Dolly   |  8.5 | 1946-01-19 |
| Etta    |    9 | 1938-01-25 |
| Irma    |    7 | 1941-02-18 |
| Barbara |  7.5 | 1948-12-25 |
| Gladys  |    8 | 1944-05-28 |
| NULL    | NULL | 1946-05-02 |
+---------+------+------------+
6 rows in set (0.00 sec)

左右の結合は、句の「+ OUTER 」部分が暗示されているものの、「 LEFT OUTER JOIN 」または「 RIGHT OUTER JOIN 」として記述できることに注意してください。 同様に、 ` INNER JOIN`を指定すると、単に` + JOIN`を記述するのと同じ結果になります。

`+ JOIN `を使用して複数のテーブルからレコードをクエリする代わりに、 ` UNION +`句を使用できます。

`+ UNION `演算子は、 ` JOIN `句とは少し異なる動作をします:単一の ` SELECT `ステートメントを使用して複数のテーブルの結果を一意の列として出力する代わりに、 ` UNION `は2つの ` SELECT +`ステートメントの結果単一の列に。

例として、次のクエリを実行します。

SELECT name FROM tourneys UNION SELECT name FROM dinners;

このクエリは重複したエントリを削除します。これは `+ UNION`演算子のデフォルトの動作です:

Output+---------+
| name    |
+---------+
| Dolly   |
| Etta    |
| Irma    |
| Barbara |
| Gladys  |
| Bettye  |
| Lesley  |
+---------+
7 rows in set (0.00 sec)

すべてのエントリ(重複を含む)を返すには、 `+ UNION ALL +`演算子を使用します。

SELECT name FROM tourneys UNION ALL SELECT name FROM dinners;
Output+---------+
| name    |
+---------+
| Dolly   |
| Etta    |
| Irma    |
| Barbara |
| Gladys  |
| Bettye  |
| Dolly   |
| Etta    |
| Irma    |
| Barbara |
| Gladys  |
| Lesley  |
+---------+
12 rows in set (0.00 sec)

結果テーブルの列の名前と数は、最初の + SELECT +`ステートメントでクエリされた列の名前と数を反映しています。 `+ UNION +`を使用して複数のテーブルから複数の列をクエリする場合、各 `+ SELECT +`ステートメントは同じ数の列をクエリする必要があり、それぞれの列は同様のデータ型を持ち、各 `+ SELECT +`の列は文は同じ順序でなければなりません。 次の例は、異なる数の列をクエリする2つの `+ SELECT`ステートメントで + UNION`句を使用した場合の結果を示しています。

SELECT name FROM dinners UNION SELECT name, wins FROM tourneys;
OutputERROR 1222 (21000): The used SELECT statements have a different number of columns

複数のテーブルをクエリする別の方法は、_subqueries_を使用することです。 サブクエリ(_inner_または_nested querysとも呼ばれます)は、別のクエリに囲まれたクエリです。 これらは、個別の集計関数の結果に対してクエリの結果をフィルター処理する場合に役立ちます。

この考えを説明するために、Barbaraよりも多くの試合に勝った友達を知りたいとしましょう。 Barbaraが勝ったマッチの数を照会してから、別のクエリを実行して、それ以上のゲームに勝った人を確認するのではなく、1つのクエリで両方を計算できます。

SELECT name, wins FROM tourneys
WHERE wins > (
SELECT wins FROM tourneys WHERE name = 'Barbara'
);
Output+--------+------+
| name   | wins |
+--------+------+
| Dolly  |    7 |
| Etta   |    4 |
| Irma   |    9 |
| Gladys |   13 |
+--------+------+
4 rows in set (0.00 sec)

このステートメントのサブクエリは一度だけ実行されました。 `+ name `列の ` Barbara `と同じ行の ` wins +`列から値を見つけるだけでよく、サブクエリと外部クエリによって返されるデータは互いに独立しています。 ただし、必要なデータを返すために、外部クエリが最初にテーブル内のすべての行を読み取り、それらの値をサブクエリによって返されたデータと比較する必要がある場合があります。 この場合、サブクエリは_correlated subquery_と呼ばれます。

次のステートメントは、相関サブクエリの例です。 このクエリは、同じ靴のサイズの友達の平均よりも多くのゲームに勝った友達を見つけようとします。

SELECT name, size FROM tourneys AS t
WHERE wins > (
SELECT AVG(wins) FROM tourneys WHERE size = t.size
);

クエリを完了するには、最初に外部クエリから「+ names」列と「+ size of」列を収集する必要があります。 次に、その結​​果セットの各行を内部クエリの結果と比較します。これにより、同じ靴サイズの個人の平均勝利数が決定されます。 同じ靴サイズの友人は2人しかいないため、結果セットには1行しか存在できません。

Output+------+------+
| name | size |
+------+------+
| Etta |    9 |
+------+------+
1 row in set (0.00 sec)

前述のように、サブクエリを使用して、複数のテーブルから結果をクエリできます。 最後の例でこれを説明するために、グループの史上最高のボウラーにサプライズディナーを投げたいとしましょう。 次のクエリを使用すると、ボウリングの記録が最高の友達を見つけて、お気に入りの食事を返すことができます。

SELECT name, entree, side, dessert
FROM dinners
WHERE name = (SELECT name FROM tourneys
WHERE wins = (SELECT MAX(wins) FROM tourneys));
Output+--------+--------+-------+-----------+
| name   | entree | side  | dessert   |
+--------+--------+-------+-----------+
| Gladys | steak  | fries | ice cream |
+--------+--------+-------+-----------+
1 row in set (0.00 sec)

このステートメントにはサブクエリが含まれているだけでなく、そのサブクエリ内にサブクエリも含まれていることに注意してください。

結論

クエリの発行は、データベース管理の領域内で最も一般的に実行されるタスクの1つです。 phpMyAdminやhttps://www.pgadmin.org/[pgAdmin]などの多くのデータベース管理ツールがあり、クエリを実行して結果を視覚化できます。しかし、コマンドラインから「+ SELECT +」ステートメントを発行することは依然として広く実践されているワークフローであり、より優れた制御を提供できます。

SQLを初めて使用する場合は、https://www.digitalocean.com/community/tutorials/how-to-manage-sql-database-cheat-sheet [SQL Cheat Sheet]を使用することをお勧めします参照し、https://dev.mysql.com/doc/refman/5.7/en/ [公式のMySQLドキュメント]を確認してください。 さらに、SQLおよびリレーショナルデータベースの詳細を知りたい場合は、次のチュートリアルが役立ちます。