web-dev-qa-db-ja.com

MySQLでHAVINGがSELECTエイリアスを使用できるのはなぜですか?

SQLでは、私の知る限り、概念的な解釈順序である論理クエリの処理順序は、次のようにFROMで始まります。

  1. から
  2. どこ
  3. GROUP BY
  4. 持っている
  5. 選択する
  6. 注文する

このリストをたどると、エイリアスがまだ作成されていないため、WHERE句にSELECTエイリアスを設定できない理由が簡単にわかります。 T-SQL(SQL Server)はこれに厳密に従っており、SELECTを渡すまでSELECTエイリアスを使用できません。

ただし、MySQLでは、(論理的に)SELECT句の前に処理する必要がある場合でも、HAVING句でSELECTエイリアスを使用できます。これはどのようにして可能ですか?

例を挙げましょう:

SELECT YEAR(orderdate), COUNT(*) as Amount
FROM Sales.Orders
GROUP BY YEAR(orderdate) 
HAVING Amount>1;

ステートメントはT-SQLでは無効です(HAVINGがSELECTエイリアスAmountを参照しているため)...

Msg 207, Level 16, State 1, Line 5
Invalid column name 'Amount'.

...しかし、MySQLでは問題なく動作します。

これに基づいて、私は疑問に思います:

  • MySQLはユーザーを助けるためにSQLルールのショートカットを取っていますか?たぶん、何らかの事前分析を使用していますか?
  • または、MySQLは、すべてのRDBMSが従ったものとは異なる概念解釈順序を使用していますか?
14
Ohlin

まあ、この種の質問がある場合、私見の情報源はMySQLのドキュメントです。さてポイントに。これは、デフォルトで有効になっているGROUP BYへのMySql拡張の動作です。

GROUP BYのMySQL拡張
MySQLはこの動作を拡張し、集計列のHAVING句でエイリアスを使用できるようにします

標準の動作が必要な場合は、sql_modeONLY_FULL_GROUP_BY を使用してこの拡張機能を無効にできます

SET [SESSION | GLOBAL] sql_mode = ONLY_FULL_GROUP_BY;

上記のクエリをONLY_FULL_GROUP_BY sql_modeで実行しようとすると、次のエラーメッセージが表示されます。

非グループ化フィールド 'Amount'がHAVING句で使用されています:SELECT YEAR(orderdate)、COUNT(*)as Amount FROM Orders GROUP BY YEAR(orderdate)HAVING Amount> 1

これはSQLFiddleデモです

したがって、MySQLのインスタンスを構成して使用する方法は、あなた次第です。

13
peterm

良い質問。

これらのクエリを実行する必要があると思います

EXPLAIN SELECT YEAR(orderdate), COUNT(*) as Amount
FROM Sales.Orders
GROUP BY YEAR(orderdate) 
HAVING Amount>1;
SHOW WARNINGS;

クエリがどのように書き換えられたかを確認します。クエリオプティマイザーがAmountをCOUNT(*)に置き換えることを確認してください

SELECT YEAR(orderdate), COUNT(*) as Amount
FROM Sales.Orders
GROUP BY YEAR(orderdate) 
HAVING COUNT(*)>1;

それのように

select 
 *
from 
 test
where 
 id = 5 - 3

クエリオプティマイザーの後は、このようなものです。

select 
 test.id as 'id'
from 
 test
where 
 test.id = 2
4
Raymond Nijland