「データベース間でSQLの実行順序が異なる方法」

「SQLの実行順序がデータベース間で異なる方法」

なぜSQL Serverでは序数の位置でGROUP BYできず、他のデータベースではできるのか

Transact-SQL vs MySQL execution order (image by author)

MySQLやPostgreSQLなどのオープンソースのデータベースと定期的に作業していた私は、最近SQL Serverプロジェクトで作業する機会があり、SQLの世界に微妙で重要な違いを発見しました。SQL Serverでは、序数位置(GROUP BY 1, 2, 3…)でのGROUP BYができず、これは私が他のデータベースで特に迅速なテストのために頻繁に使用していた機能でした。

この発見により、両データベースシステムのいくつかの微妙なニュアンス、特にSQLの実行順序について調査する機会が得られました。

これが重要な理由は何でしょうか?データベースシステムで作業する際に、微妙な違いを理解することは、ワークフローに大きな影響を与え、生産性を高めることができます。大幅なトラブルシューティング時間を節約することができます。さらに、さまざまなデータベースのSQL実行順序を理解することで、作業しているシステムに基づいてより最適なSQLクエリを作成することができます

この記事では、この動作が発生する一連の主な使用例であるGROUP BYについて調べ、なぜそのような仕組みになっているのかを調査します。ただし、この洞察はHAVING、WHERE、または他のSQLコマンド句にも適用することができます。

始めましょう

以下のクエリの例を見てみましょう。これはMySQLでは機能しますが、SQL Serverでは機能しません:

SELECT    DATEPART(year, day) AS order_date,    SUM(cost) as costFROM cleanGROUP BY 1;

これを実行すると、おそらく次のようなエラーが表示されるでしょう:

Each GROUP BY expression must contain at least one column that is not an outer reference.

ただし、これを修正したクエリでは、明示的な表現でGROUP BY序数参照を置き換えると動作します。また、ORDER BY句では序数位置を参照できることも気づくでしょう:

SELECT    datepart(year, day),    sum(cost) as costfrom cleanGROUP BY datepart(year, day)ORDER BY 1;

SQL Serverでは、GROUP BY句で明示的な列名または表現を使用する必要があるとすぐに学びました。これはコードを理解しやすくするためのベストプラクティスとされています。しかし、なぜこの動作がデータベース間で異なるのかについては興味深く思いました。さらにSQL ServerのORDER BY句が序数位置で動作することも興味深いと思いました。

SELECT文の実行順序の調査

SQL Serverと他のデータベースのSELECT文の実行/処理順序を見てみましょう。SQLデータベースでは、クエリの各パートは順次実行され、その順序は書かれた順序とは異なります。

たとえば、SQL Serverでは以下の画像およびMicrosoftドキュメントから分かるように、FROM句が最初に評価されることがわかります。さらに、SELECT句はGROUP BY句の後に実行されます。これが最初の例でGROUP BY句で列の位置やエイリアスを参照できなかった理由です。

しかし、ORDER BY句では序数位置やエイリアスを参照することができます。これはSELECT句の後に評価されるためです。SELECT句はデータベースに返される列を伝えるため、この時点で位置がわかっています。面白いですね?

SQL Serverの実行順序

SQL Server SELECT statement processing order (Image by author)

MySQL(マイエスキューエル)

ただし、MySQLでは、SQLクエリの実行順序を明示的に示したドキュメントを見つけることが難しいと感じました。実行順序はクエリの内容とクエリオプティマイザが最適なパスと定義する内容によって異なるようです。

しかし、MySQLのドキュメントからわかるように、SELECT文はGROUP BY節よりも先に評価されることが示されています:

GROUP BY句やHAVING句では、select_exprの値を検索する前にFROM句を検索します。(GROUP BYやHAVINGの場合、これはORDER BYと同じルールを使用したMySQL 5.0以前の動作とは異なります。)

GoogleSQL(グーグルエスキューエル)

また、Google BigQueryで使用されるGoogleSQL(以前は標準SQLと呼ばれていました)ドキュメントも参照すると、SQL Serverとは異なるクエリの実行方法が見られます:

GROUP BYおよびORDER BYは、SELECTリスト内の項目を指す第三のグループである整数リテラルも参照できます。整数1はSELECTリストの最初の項目を指し、2は2番目の項目を指し、以下同様です。

ご覧の通り、この動作はSQL Serverではサポートされていません。Googleのドキュメントでは、GROUP BY、ORDER BY、およびHAVINGは、SELECTリストのエイリアスを参照できるとも述べています。

これにより、これらの他のデータベースの実行順序が以下の画像に示すようなパスに従うことが高い確率であると結論づけることができます:

MySQL(マイエスキューエル)、PostgreSQL(ポースクエル)およびBigQuery(ビッグクエリ)の推定実行順序

MySQL SELECT文の実行順序(画像提供:著者)

結論

今回は、観察された動作とドキュメントに基づいて、MySQL、GoogleSQL、および他のデータベースのSQL構文における実行順序がSQL Serverと異なることを見てみました。SQL Serverはコードの明確さのためにGROUP BY句で明示性を強調していますが、MySQLの実行順序では明確にSELECT句をGROUP BY句の前に評価して、その中の序数の位置を参照できるようになっています。

このトピックに関するご意見をお気軽に共有していただき、次回にお会いしましょう。

私をサポートし、このようなストーリーをもっと楽しむために、VoAGIメンバーになることもできます。

参考文献

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more