SQLはデータベースの言語であり、PostgreSQLが私たちが選んだ言語です。多くの場合、データの保存はプロセスの1つの側面にすぎません。通常、データ中心の取り組みでは、データの表示と読み取り、データに対するアクションの実行または変更の実装、意思決定情報(分析)の収集、または何らかの形式または方法で保存されたデータの操作を行います。
SQLは、キーワード、コマンド、および句の組み合わせで構成されています。 SQLは単純なようです。ほんの数'簡単 'あちこちのコマンド。大したことじゃないですよね?
しかし、SQLには目に見える以上のものがあります。 SQLはそれらの'簡単にあなたをつまずかせることができます 'クエリ。
1つの課題(私は定期的に再検討する必要があります)は、SQLの実行順序がその構文の実行順序とは明らかに異なることを理解することです。
このブログ投稿では、PostgreSQLに適用される主要なSQL句を大まかに説明します。 SQLには多くの方言がありますが、ここではPostgreSQLの解釈に焦点を当てています。 (各句のいくつかの特性は、他のSQL方言にも当てはまる可能性があります。)
SQL句は、基本的な、頻繁に使用されるコマンドとクエリの基盤を形成します。そうは言っても、ウィンドウ関数、CTE、派生テーブルなどを利用した高度なクエリと例については、この投稿では取り上げません。
後でわかるように、すべての句が同じように作成されるわけではありません。それでも、これらは連携して動作し、クエリ結果をシームレスに提供します(または提供しません)。
明確にさせてください...
多くの条項に適用されるため、ブログ投稿全体で実行順序について定期的に言及します。しかし、これは一般化されています。
私の理解では、多くの場合、オプティマイザは実行に最適なクエリプランを選択して決定します。
SELECT-データベースのクエリに使用される「picky」句
SELECTは1つのビジー句です。どこにでもあります。他のすべての句よりも多く使用されました。まったく必要ないかもしれない特定の条項。 SELECTは必須の句であるため、それほど多くはありません。
SELECT句は通常、データベースのクエリに使用され、(基本レベルで)次のものが含まれます。
- SELECTリスト-必要なデータの列。
- ソースデータセット-FROM句で指定されています。テーブル、ビュー、CTEなど。ここからデータが取得されます。
- FROM句によって提供される行をフィルタリングするために使用されるオプションのWHERE句。
(FROM句とWHERE句については、それぞれのセクションで説明します。)
実は、PostgreSQLでは何かを取得するためにSELECT句が必要だと思います。ただし、テーブルからすべての行と列を返すTABLEコマンドがあります。
それでも、2つの間に分離があります。 SELECTは個々の列を指定できますが、TABLEコマンドを使用すると、すべての列が返されます。
ハイライトの選択:
- SELECT *は省略表記であり、データソースからすべての列を返します。
- SELECTは構文的に最初の句として名前が付けられていますが(WITH句を使用するクエリを除く:ここでは説明しません)、最初に実行されることはありません。特に、SELECTは実行する最後の句ではありません。
- 式(または任意の列)には、SELECT句で参照名またはALIASを指定できますが、注意が必要です。これらの名前は、ORDERBY句とGROUPBY句で使用できますが、WHERE句やHAVING句では使用できません。
- クエリにGROUPBY句(または集計関数)が存在する場合、SELECTはグループ化されていない列に名前を付けないでください。集計関数内の列、またはグループ化された列に機能的に依存している列のみ。
- SELECTは特定の列を返すだけでなく、その使用はINSERTおよびCREATETABLEステートメントにも拡張されます。
- SELECT句は単純ではありません。
詳細については、PostgreSQLの公式SELECT句のドキュメントセクションを参照してください。
FROM-クエリのデータソースを提供します
FROMは主に必須の句です。私はこれを「大まかに」と呼びます 'FROM句を必要としない利用可能なTABLEコマンド(上記)のため。
次に、SELECTクエリで名前付きテーブルを使用せずに、任意の式を選択できます。ただし、TABLEではそれは不可能です。
これがpsqlの例です:
learning=> SELECT 2+2;
?column?
----------
4
(1 row)
しかし、TABLEを使用する場合:
learning=> TABLE 2+2;
ERROR: syntax error at or near "2"
LINE 1: TABLE 2+2;
^
一部のSQLダイアレクトでは、存在しないテーブルに名前を付けて、FROM句に実際のテーブルがないことを軽減することもできます。ただし、上記の単純なクエリからわかるように、PostgreSQLでは必須ではありません。
ただし、単純な式とは別に実際に保存されたデータを返す必要がある場合は、FROM句が必要になります。それがなければ、操作するデータさえありません。
したがって、テーブルのクエリにはFROMが絶対に必要です。
Postgresでは、FROM句内のすべての名前付きテーブルは、デカルト積を確立する実行順序で最初に相互結合されます(WITH句が存在しない場合)。作業するデータが必要なので、これは理にかなっています。
ここでのFROMのドキュメントには、通常、このデータセットは現在のWHERE句の条件によって少数の行に削減されることも記載されています。
FROM句は、いくつかの特定の要素を受け入れます。ここにいくつかあります(完全なリストについては、以下のリンクドキュメントを参照してください):
- テーブル名(明らかにこれが必要です)。
- ビュー。
- SELECTステートメント(サブクエリ)。
- CTE名(WITH句)。
- JOINのタイプ-存在する場合。
- 関数(私はこれに気づいていませんでした。なんてクールな!!!)
FROMのハイライト:
- FROMは構文的にSELECTクエリの2番目の句としてリストされていますが、最初に実行されます。
- FROMは、その句で指定された任意のテーブル(実数または仮想)からすべての行を(ロードすることによって)提供します。
- テーブル名はFROM句でエイリアス化できます(例:FROMshoes AS)が、クエリ全体を通してそのALIASによって参照される必要があります。
- FROMは、テーブルをクエリする際の必須の句です。
詳細については、PostgreSQLの公式FROM句のセクションを参照してください。
WHERE-ブール検証条件式に基づいてデータソースから行を除外します
WHEREはオプションの句です。ただし、クエリに存在する場合、その義務は、ブール条件チェックに合格しないFROM句によって提供されるレコードを削除することです。
WHERE句は、SELECTに加えて、他のSQLコマンドでも深く使用されます。つまり、INSERT(直接ではなく、SELECTを介して)、UPDATE、DELETEなどのDMLコマンド。
実際のところ、WHERE句がないと、UPDATEステートメントとDELETEステートメントがすべてのターゲット行に影響を与える可能性があります。おそらくあなたが意図したものではないでしょう(そうです!)。
WHERE句のブール条件式では、集計関数を使用できません。実行順序でのグループ化はまだ行われていません。したがって、WHERE句では(まだ)集計は使用できません。
WHERE評価は、比較演算子のいずれかを使用したブールチェックに基づいています。 (例:>、<、=、<>など)
WHERE句は、SELECT句にリストされているエイリアス列名にアクセスできません。 SELECT句は実際にはなので (構文的にではなく)WHERE句の後に実行されたため、これらのエイリアス列はまだ使用できません。
場所のハイライト:
- 集計関数にはアクセスできず、WHERE句のブール条件付きチェックでは使用できません。 (WHERE句は、関数を集約し、計算のためにグループ化するために提供されるすべての行を担当する可能性があります。)
- SELECT句のエイリアス列はWHERE句で参照できません。
- WHERE句のブール式の条件付きチェックでは、true、false、またはNULLのいずれかになります。
- WHERE句のブール式がfalseまたはNULLと評価される行はすべて削除されます。
- ANDまたはORキーワードを使用して、WHERE句で複数のブール条件をチェックできます。
詳細については、PostgreSQLの公式WHERE句のセクションを参照してください。
GROUPBY-フォームグループ
オプションの句です。
この句は、選択されたものに対して単一の行を作成します。これには、指定されたグループ化された列の値との一致が含まれます。
GROUP BYは扱いにくい場合があるため、ドキュメントからこの一節を含めるのが適切だと思います。
「GROUPBYが存在する場合、または集計関数が存在する場合、集計関数内を除いて、またはグループ化されていない列がグループ化された列に機能的に依存している場合を除いて、SELECTリスト式がグループ化されていない列を参照することは無効です。グループ化されていない列に対して返される可能性のある値が複数あります。グループ化された列(またはそのサブセット)がグループ化されていない列を含むテーブルのプライマリキーである場合、機能の依存関係が存在します。」
GROUP BYのハイライト:
- Postgresでは、ソーステーブルの列だけでなく、SELECT列リストにリストされている列もグループ化できます。これは厳密なSQLとは少し異なります。
- 特定のクエリでは、GROUP BYは、SELECT句の列の重複する値を削除することでDISTINCT句を模倣できます。
- 列の順序はGROUPBYには関係ありません。
- GROUP BY句の対象とならない列は、集計以外では参照できません。
- 多くの場合、主キーの機能に依存する列の主キーをグループ化できます。
- GROUP BY句がない場合でも、集計関数を使用するクエリに対してグループ化が実行されます。
詳細については、PostgreSQLの公式GROUPBY句のセクションをご覧ください。
HAVING-GROUPBY列と集計関数をフィルター処理します
オプションの句です。
HAVINGは、WHERE句と同じようにブール条件チェックを使用して結果セットから行をフィルタリングしますが、GROUPBY句や集計関数によって形成された行をフィルタリングします。
ハイライトがある:
- HAVING句は、GROUP BY列に加えて、集計関数で指定された列(グループ化されていない列も含む)を参照できます。
- HAVINGは、集計関数またはグループ化が適用された後に行を削除する責任があります。
- HAVING句で集約されていない列を参照できますが、そうすることはほとんど役に立ちません。
- HAVING句はGROUPBY句と組み合わせて使用されることがよくありますが、単独で使用することもできます。クエリ結果は、集計関数でのみこれらの列の単一のグループに形成されます。
詳細については、PostgreSQLの公式HAVING句のセクションを参照してください。
ORDERBY-ランダム性から外れた順序の測定
オプションの句です。
特定の注文が必要な場合は、ORDERBYを使用してください。それ以外の場合、データベースは任意の順序で結果を返すことができます(そして返すでしょう)。
結果がある程度の順序で表示されたとしても、これは保証されません。
だまされてはいけません。 ORDERBYを使用します。
利用可能な注文パターンは2つあります。 ASC(昇順)またはDESC(降順)のいずれかの順序で、ASCがデフォルトです。
結果セットにNULL値を含める場合は、次のように順序付けに使用することもできます。NULLSLASTを指定すると、NULL以外の値の後にソートされますが、NULLSFIRSTを要求するとその逆になります。
ORDER BYハイライト:
- 並べ替え式は、クエリのSELECTリストで許可される式のいずれかです。
- PostgreSQLでは、一部のSQLダイアレクトにはないSELECT句に存在しないORDERBY列を使用できます。
- クエリ結果は気まぐれであり、ORDER BY句を使用しない限り、パターンや順序に似ているとは限りません。
- ORDER BYとLIMIT句(次のセクションを参照)は、'トップを決定するのに最適です。 '行の結果セット。 (例:最も売れ行きの良い5日間、最も売れ行きの悪い5足の靴、今四半期のトップセールスマン)
- SELECTリストの列位置番号で結果を並べ替えることができますが、指定する番号は、上記のSELECT句リストの項目数を超えてはなりません。つまり、SELECT句に項目が2つしかない場合、ORDERBY3はエラーを生成します。
- 個々の式は、リストされているオプションによってのみ順序付けられます。 (例:ORDER BY col_1 DESC、col_2DESCはORDERBY col_1、col_2 DESCと同じではありません)
詳細については、PostgreSQLの公式ORDERBY句のセクションを参照してください。
今日のホワイトペーパーをダウンロードするClusterControlを使用したPostgreSQLの管理と自動化PostgreSQLの導入、監視、管理、スケーリングを行うために知っておくべきことについて学ぶホワイトペーパーをダウンロードするLIMIT-クエリ結果から特定の行数を取得する
LIMITはオプションの句です。
LIMITは実際には2つの副節で構成されており、OFFSETが2番目の節です。
句のOFFSET部分に値が指定されている場合、結果セットの行は後に返されます。 その行数をスキップします。
注意すべきドキュメントの重要なセクション:
「クエリプランナーはクエリプランを生成するときにLIMITを考慮に入れるため、LIMITとOFFSETに使用するものに応じて、異なるプランを取得する(異なる行の順序を生成する)可能性が非常に高くなります。したがって、異なるLIMIT / OFFSET値を使用して、異なるものを選択します。 ORDER BYを使用して予測可能な結果の順序を強制しない限り、クエリ結果のサブセットは一貫性のない結果をもたらします。これはバグではありません。SQLが特定の順序でクエリの結果を提供することを約束しないという事実の固有の結果です。 ORDERBYを使用して順序を制限しない限り。」
LIMITのハイライト:
- クエリ自体が結果セットで生成する行が少ない場合、LIMITは定義された数よりも少ない行を返す可能性があります。つまり、返される行の数には影響しません。
- LIMIT ALL構文は受け入れ可能であり、LIMIT句をまったく含めないのと同じ効果があります。
- OFFSET句が原因で「x」行数がスキップされますが、これは「回避策」ではありません。 'サーバーのクエリプランに対して計算されるため、パフォーマンスが向上します。
- OFFSET 0は、OFFSET句をまったく含まないことと同じです。
詳細については、PostgreSQLの公式LIMIT条項のセクションをご覧ください。
PostgreSQLによる主要なSQL句の解釈は独自のものです。 PostgreSQLがそれらを実装する方法を選択するかどうかに関係なく、それらはSQLクエリの基礎であり、個々の特性(およびニュアンス)に精通していることは、前進するユーザーにのみ利益をもたらします。
これらの各条項には、大量の記事、書籍、ドキュメント、ブログ投稿が書かれていますが、この高レベルの概要がわかりやすく、有益であると感じていただければ幸いです。
読んでいただきありがとうございます。