回答:
MySQLのWHEREではなくHAVINGの後に、自分で作成した列(「select 1 as number」など)を配置する必要があるのはなぜですか?
WHERE
はGROUP BY
、の前にHAVING
適用され、後に適用されます(および集計でフィルタリングできます)。
一般に、これらの句のどちらでもエイリアスを参照することはできますが、およびでレベルエイリアスをMySQL
参照できます。SELECT
GROUP BY
ORDER BY
HAVING
そして、「WHERE 1」を実行する代わりに欠点があります(列名の代わりに定義全体を書き込みます)
計算式に集計が含まれていない場合は、それをWHERE
句に入れる方が効率的です。
この質問に対する他のすべての回答は、要点に当てはまりませんでした。
テーブルがあると仮定します。
CREATE TABLE `table` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`value` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `value` (`value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
そして、IDと値の両方が1から10の10行があります。
INSERT INTO `table`(`id`, `value`) VALUES (1, 1),(2, 2),(3, 3),(4, 4),(5, 5),(6, 6),(7, 7),(8, 8),(9, 9),(10, 10);
次の2つのクエリを試してください。
SELECT `value` v FROM `table` WHERE `value`>5; -- Get 5 rows
SELECT `value` v FROM `table` HAVING `value`>5; -- Get 5 rows
まったく同じ結果が得られ、HAVING句はGROUP BY句なしでも機能することがわかります。
ここに違いがあります:
SELECT `value` v FROM `table` WHERE `v`>5;
エラー#1054-「where句」の不明な列「v」
SELECT `value` v FROM `table` HAVING `v`>5; -- Get 5 rows
WHERE句を使用すると、条件で任意のテーブル列を使用できますが、エイリアスや集計関数は使用できません。HAVING句を使用すると、選択した(!)列、エイリアス、または集計関数を条件で使用できます。
これは、WHERE句は選択前にデータをフィルタリングしますが、HAVING句は選択後に結果のデータをフィルタリングするためです。
したがって、テーブルに多数の行がある場合は、条件をWHERE句に入れる方が効率的です。
EXPLAINを試して、主な違いを確認します。
EXPLAIN SELECT `value` v FROM `table` WHERE `value`>5;
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
| 1 | SIMPLE | table | range | value | value | 4 | NULL | 5 | Using where; Using index |
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
EXPLAIN SELECT `value` v FROM `table` having `value`>5;
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+
| 1 | SIMPLE | table | index | NULL | value | 4 | NULL | 10 | Using index |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+
WHEREまたはHAVINGがインデックスを使用していることがわかりますが、行は異なります。
SELECT value, COUNT(*) frequency FROM table GROUP BY value HAVING frequency > 10
...HAVING clause can use both column and alias.
へ...HAVING clause can use either column or alias.
と変更...WHERE clause will be more effective
へ...WHERE clause will be more efficient
HAVING
内の集計をフィルタリングするために使用されますGROUP BY
。
たとえば、名前の重複をチェックするには、次のようにします。
SELECT Name FROM Usernames
GROUP BY Name
HAVING COUNT(*) > 1
これらの2つは、データをフィルタリングするための条件について言うために使用されるため、最初と同じように感じられます。どのような場合でも「where」の代わりに「having」を使用できますが、「having」の代わりに「where」を使用できない場合があります。これは、選択クエリでは、「where」は「select」の前にデータをフィルタリングし、「haven」は「select」の後にデータをフィルタリングするためです。したがって、実際にはデータベースにないエイリアス名を使用する場合、「where」はそれらを識別できませんが、「having」は識別できます。
例:テーブルStudentに、student_id、name、birthday、addressを含めます。誕生日のタイプは日付です。
SELECT * FROM Student WHERE YEAR(birthday)>1993; /*this will work as birthday is in database.if we use having in place of where too this will work*/
SELECT student_id,(YEAR(CurDate())-YEAR(birthday)) AS Age FROM Student HAVING Age>20;
/*this will not work if we use ‘where’ here, ‘where’ don’t know about age as age is defined in select part.*/
WHERE
とHAVING
。
WHEREは、データがグループ化される前にフィルタリングし、HAVINGは、データがグループ化された後にフィルタリングします。これは重要な違いです。WHERE句によって削除された行はグループに含まれません。これにより、計算された値が変更され、その結果(=結果として)、HAVING 句でのそれらの値の使用に基づいてフィルタリングされるグループに影響を与える可能性があります。
そして続けます
HAVINGはWHEREに非常に似ているため、GROUP BYが指定されていない場合、ほとんどのDBMSはそれらを同じものとして扱います。それでも、自分で区別する必要があります。HAVINGは、GROUP BY 句と組み合わせてのみ使用してください。標準の行レベルのフィルタリングにはWHEREを使用します。
抜粋: フォルタ、ベン。「Sams Teach Yourself SQL in 10 Minutes(5th Edition)(Sams Teach Yourself ...)」。