2017-08-28 5 views
0

1回のクエリでCOUNT(column_name)を2回使用することのパフォーマンスが不思議です。ここで問題になっているクエリは次のとおりです。MySQL:列リストでCOUNT(column_name)を使用し、再度HAVING節で使用します。これにより、COUNT(column_name)操作が2回実行されますか?

SELECT 
    employee_name, 
    COUNT(employee_name) 
FROM 
    employee 
GROUP BY 
    employee_name 
HAVING 
    COUNT(employee_name) > 1; 

は二回

COUNT(employee_name) 

実行されますか?さらに、将来このような質問があるときに、どのようなことが起こっているのかを自分で確認できますか?

ありがとうございます!

+0

'employee_nameがNULLである行をカウントしないようにしたい場合を除き、' COUNT(*) 'を使用してください。 –

答えて

-1

は、任意の便利なテーブルを選択し、次の操作を行います。

Using `rand()` with `having`

Is there Performance related difference in using aggregate function in ORDER BY clause and alias of aggregate function?

そして私は非RANDの例を含む他の議論があると思う:

mysql> SELECT RAND() AS r FROM canada HAVING r < 0.1 limit 11; 
+-----------------------+ 
| r      | 
+-----------------------+ 
| 0.6982369559800596 | 
| 0.33121224616767114 | 
| 0.3811396559524719 | 
| 0.4718028721136999 | 

も参照してください。

元の質問は、両方の状況で同じ値を提供するCOUNT(employee_name)を使用しています。だから、それが本当に2回評価されたかどうかは分かりません。 RAND()を使用すると、再評価されたことが明らかになります。

+1

これはIMOの良い例ではありません。あなたのクエリ 'HAVING'は本当に' WHERE'のように動作しているからです。このような方法で「HAVING」がオーバーロードされていることは、MySQLの特徴の1つです。 –

+0

@TimBiegeleisen - 私の指摘は、エイリアスにもかかわらず、明らかに再評価しています。 –

+0

良い点+1。私は私の答えを更新し、あなたが言ったことを引用します。しかし、いずれにしても、OPは主に「GROUP BY」クエリのコンテキストで尋ねていたと思います。 –

2

オプティマイザ・トレースを使用して、オプティマイザが問合せを実行する方法とその理由を知ることができます。この特定のケースでは、トレースは、明示的にカウントが計算された回数を教えてくれないが、我々は、集計を実行するために使用される一時テーブルについての情報を得ることができますについては


mysql> SET optimizer_trace='enabled=on';            
Query OK, 0 rows affected (0,00 sec) 

mysql> SELECT c2, COUNT(c2) FROM temp GROUP BY c2 HAVING COUNT(c2) > 1; 
+------+-----------+ 
| c2 | COUNT(c2) | 
+------+-----------+ 
| 1 |   2 | 
| 2 |   2 | 
+------+-----------+ 
2 rows in set (0,00 sec) 

mysql> SELECT trace->'$.steps[*].join_execution.steps[*].creating_tmp_table' 
    -> FROM information_schema.optimizer_trace; 
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| trace->'$.steps[*].join_execution.steps[*].creating_tmp_table'                            | 
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| [{"tmp_table_info": {"table": "intermediate_tmp_table", "location": "memory (heap)", "key_length": 5, "row_length": 23, "unique_constraint": false, "row_limit_estimate": 729444}}] | 
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
1 row in set (0,01 sec) 

mysql> SELECT c2, COUNT(c2) AS c FROM temp GROUP BY c2 HAVING c > 1; 
+------+---+ 
| c2 | c | 
+------+---+ 
| 1 | 2 | 
| 2 | 2 | 
+------+---+ 
2 rows in set (0,00 sec) 

mysql> SELECT trace->'$.steps[*].join_execution.steps[*].creating_tmp_table'   -> FROM information_schema.optimizer_trace; 
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| trace->'$.steps[*].join_execution.steps[*].creating_tmp_table'                              | 
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| [{"tmp_table_info": {"table": "intermediate_tmp_table", "location": "memory (heap)", "key_length": 5, "row_length": 14, "unique_constraint": false, "row_limit_estimate": 1198372}}] | 
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
1 row in set (0,00 sec) 

COUNT式を繰り返す代わりにエイリアスを使用すると、一時テーブルの行サイズは小さくなります(14対23バイト)。これは、クエリでは集計中に2回カウントされることを示します。

関連する問題