web-dev-qa-db-ja.com

どこでHAVING

MySQLでHAVINGではなくWHEREの後に自分で作成した列(例えばselect 1 as "number")を配置する必要があるのはなぜですか?

WHERE 1(カラム名の代わりに定義全体を書く)の代わりに何か欠点がありますか?

234
baloo

MySQLでWHEREではなくHAVINGの後に自分で作成した列(たとえば「select 1 as number」)を配置する必要があるのはなぜですか?

WHEREGROUP BYの前に適用され、HAVINGは後に適用されます(そして集約をフィルタリングすることができます)。

一般に、これらの句のどちらでもエイリアスを参照することはできませんが、MySQLでは、GROUP BYORDER BY、およびSELECTHAVINGレベルのエイリアスを参照できます。

そして "WHERE 1"(カラム名の代わりに定義全体を書く)をする代わりに何か欠点がありますか?

計算式に集約が含まれていない場合は、それをWHERE句に含める方がおそらくより効率的です。

306
Quassnoi

すべての回答が重要なポイントに達しませんでした。

テーブルがあるとします。

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

そして、1から10までのidとvalueの両方を持つ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句がselectの前にデータをフィルタリングするのに対し、HAVING句はselectの後に結果のデータをフィルタリングするためです。

そのため、テーブルに多数の行がある場合は、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がインデックスを使用しているのがわかりますが、行が異なります。

263
Fishdrowned

主な違いは、WHEREname__はグループ化された項目(SUM(number)など)には使用できないのに対し、HAVINGname__は使用できることです。

その理由は、WHEREname__が行われるグループ化が行われ、HAVINGname__が行われるグループ化が行われるためです。

60
David Brunelle

HAVINGは、あなたのGROUP BY内の集約をフィルタリングするために使用されます。

たとえば、重複する名前を確認するには

SELECT Name FROM Usernames
GROUP BY Name
HAVING COUNT(*) > 1
39
Kevin McKelvin

両方ともデータをフィルターにかけるための条件について言うのに使用されるので、これらの2は最初のものと同じように感じるでしょう。どの場合でも、「where」の代わりに「having」を使用できますが、「having」の代わりに「where」を使用できない場合があります。これは、選択クエリでは、「選択」の前に「選択」の前にデータがフィルタ処理され、「選択」の後に「フィルタ処理」のデータが「保持」されるためです。そのため、実際にはデータベースに存在しないエイリアス名を使用する場合、「どこで」それらを識別できませんが、「持っている」ことができます。

例:テーブルStudentにstudent_id、name、birthday、addressを含めるようにします。Assumebirthdayはdate型です。

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.*/
7
Nuwantha

WHEREデータがグループ化される前にフィルタ処理し、データがグループ化された後にフィルタ処理します。これは重要な違いです。 WHERE句によって削除された行は、グループに含まれません。これにより、計算値が変更され、HAVING句での値の使用に基づいてフィルタリングされるグループが影響を受ける可能性があります。

抜粋からの引用:Forta、Ben "Samsは10分でSQLを教える(第4版)(Samsは自分を教える...)。"。

2
snr

持っていることは集約でのみ使用されますが、どこで非集約文で使用されます。

1
Hos Mercury