PostgreSQLのクエリの概要

前書き

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

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

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

PostgreSQLは、しばしば「Postgres」と短縮され、オブジェクト指向アプローチを備えたリレーショナルデータベース管理システムです。つまり、情報をPostgreSQLスキーマのオブジェクトまたはクラスとして表すことができます。 PostgreSQLは標準SQLと密接に連携していますが、他のリレーショナルデータベースシステムにはない機能も含まれています。

前提条件

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

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

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

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

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

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

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

まず、postgresスーパーユーザーとしてPostgreSQLプロンプトを開きます。

sudo -u postgres psql

[。注意]##

Note:Installing PostgreSQL on Ubuntu 18.04の前提条件チュートリアルのすべての手順を実行した場合は、PostgreSQLインストールの新しいロールを構成している可能性があります。 この場合、次のコマンドを使用してPostgresプロンプトに接続し、sammyを独自のユーザー名に置き換えることができます。

sudo -u sammy psql

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

CREATE DATABASE birthdays;

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

\c birthdays

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

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

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

OutputCREATE TABLE

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');

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

OutputINSERT 0 5

この後、同じデータベース内に別のテーブルを作成します。このテーブルは、友人のお気に入りの誕生日の食事に関する情報を保存するために使用します。 次のコマンドは、各友達のname、そのbirthdate、お気に入りのentree、好みのsideの料理の列を含むdinnersという名前のテーブルを作成します。 、および彼らのお気に入りのdessert

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

このテーブルについても同様に、テーブルが作成されたことを確認するフィードバックを受け取ります。

OutputCREATE TABLE

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

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');
OutputINSERT 0 5

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

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

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

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

SELECT column_to_select FROM table_to_select WHERE certain_conditions_apply;

例として、次のステートメントは、dinnersテーブルからname列全体を返します。

SELECT name FROM dinners;
Output  name
---------
 Dolly
 Etta
 Irma
 Barbara
 Gladys
(5 rows)

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

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)

特定の列または列のセットに名前を付ける代わりに、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)

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

. . . WHERE column_name comparison_operator value

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

オペレーター それは何ですか

=

同等性のテスト

!=

不平等のテスト

<

未満のテスト

>

大なり記号のテスト

<=

以下のテスト

>=

大なり記号以上のテスト

BETWEEN

値が指定された範囲内にあるかどうかをテストします

IN

行の値が指定された値のセットに含まれているかどうかをテストします

EXISTS

指定された条件で行が存在するかどうかをテストします

LIKE

値が指定された文字列と一致するかどうかをテストします

IS NULL

NULL値のテスト

IS NOT NULL

NULL以外のすべての値をテストします

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

SELECT size FROM tourneys WHERE name = 'Irma';
Output size
------
    7
(1 row)

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

SELECT entree FROM dinners WHERE entree LIKE 't%';
Output entree
-------
 tofu
 tofu
(2 rows)

上記の出力に基づいて、忘れたメインディッシュは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)

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

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

集約関数

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

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

SELECT COUNT(entree) FROM dinners WHERE entree = 'tofu';
Output count
-------
     2
(1 row)

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

SELECT AVG(best) FROM tourneys;
Output  avg
-------
 252.8
(1 row)

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

SELECT SUM(wins) FROM tourneys;
Output sum
-----
  35
(1 row)

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

SELECT SUM(entree) FROM dinners;
OutputERROR:  function sum(character varying) does not exist
LINE 1: select sum(entree) from dinners;
               ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

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

SELECT MIN(wins) FROM tourneys;
Output min
-----
   2
(1 row)

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

SELECT MAX(wins) FROM tourneys;
Output max
-----
  13
(1 row)

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

SELECT MIN(name) FROM dinners;
Output   min
---------
 Barbara
(1 row)

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

SELECT MAX(name) FROM dinners;
Output max
------
 Irma
(1 row)

集計関数には、このセクションで説明した以外にも多くの用途があります。 これらは、結果セットの並べ替え方法に影響を与える他のいくつかのクエリ句とともに次のセクションで説明するGROUP BY句と一緒に使用すると特に便利です。

クエリ出力の操作

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

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

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

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

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)

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)

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

SELECT COUNT(name), side FROM dinners WHERE COUNT(name) >= 3;
OutputERROR:  aggregate functions are not allowed in WHERE
LINE 1: SELECT COUNT(name), side FROM dinners WHERE COUNT(name) >= 3...

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 | side
-------+-------
     3 | fries
(1 row)

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

複数のテーブルのクエリ

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

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

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

SELECT table1.column1, table2.column2
FROM table1
JOIN table2 ON table1.related_column=table2.related_column;

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)

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

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)

tourneysテーブルにはLesleyのエントリがなく、dinnersテーブルにはBettyeのエントリがないため、これらのレコードはこの出力に含まれていないことに注意してください。

ただし、outerJOIN句を使用して、テーブルの1つからすべてのレコードを返すことは可能です。 外側のJOIN句は、LEFT JOINRIGHT JOIN、またはFULL 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 |
(6 rows)

ここで、今度はRIGHT JOIN句を使用してクエリを再度実行します。

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

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

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
         |      | 1946-05-02
(6 rows)

句のOUTERの部分が暗示されていますが、左結合と右結合はLEFT OUTER JOINまたはRIGHT OUTER JOINとして記述できることに注意してください。 同様に、INNER JOINを指定すると、JOINを書き込むのと同じ結果が得られます。

PostgreSQLを含む一部のRDBMSディストリビューションで使用できるFULL JOINと呼ばれる4番目の結合句があります。 FULL JOINは、null値を含む、各テーブルのすべてのレコードを返します。

SELECT tourneys.name, tourneys.size, dinners.birthdate
FROM tourneys
FULL 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
 Bettye  |    9 |
         |      | 1946-05-02
(7 rows)

[.note]#Note:この記事の執筆時点では、FULL JOIN句はMySQLまたはMariaDBのいずれでもサポートされていません。

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

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

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

SELECT name FROM tourneys UNION SELECT name FROM dinners;

このクエリは、重複するエントリをすべて削除します。これは、UNION演算子のデフォルトの動作です。

Output  name
---------
 Irma
 Etta
 Bettye
 Gladys
 Barbara
 Lesley
 Dolly
(7 rows)

すべてのエントリ(重複を含む)を返すには、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)

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

SELECT name FROM dinners UNION SELECT name, wins FROM tourneys;
OutputERROR:  each UNION query must have the same number of columns
LINE 1: SELECT name FROM dinners UNION SELECT name, wins FROM tourne...

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

この考えを説明するために、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)

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

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

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

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

Output name | size
------+------
 Etta |    9
(1 row)

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

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)

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

結論

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

SQLを初めて使用する場合は、SQL Cheat Sheetを参照として使用し、official PostgreSQL documenationを確認することをお勧めします。 さらに、SQLおよびリレーショナルデータベースの詳細を知りたい場合は、次のチュートリアルが役立ちます。

Related