web-dev-qa-db-ja.com

COUNT()がテーブルの1行のみを表示するのはなぜですか?

データベースpetに次のテーブルmenagerieがあります。

_+--------+-------------+---------+------+------------+------------+
| name   | owner       | species | sex  | birth      | death      |
+--------+-------------+---------+------+------------+------------+
| Tommy  | Salman Khan | Lebre   | NULL | 1999-01-13 | 0000-00-00 |
| Bowser | Diane       | dog     | m    | 1981-08-31 | 1995-07-29 |
+--------+-------------+---------+------+------------+------------+
_

次のクエリを実行すると、次のようになります。

_select owner, curdate() from pet;  
_

次の出力が得られます。

_+-------------+------------+
| owner       | curdate()  |
+-------------+------------+
| Salman Khan | 2016-09-12 |
| Diane       | 2016-09-12 |
+-------------+------------+
_

出力には、ownerのすべての値と、各行のcurdate()から返された値が表示されます。

次のクエリを実行すると、次のようになります。

_select owner, count(*) from pet;  
_

次の出力が得られます。

_+-------------+----------+
| owner       | count(*) |
+-------------+----------+
| Salman Khan |        2 |
+-------------+----------+  
_

私の質問は、curdate()count()関数の違いは何ですか。これによりMySQLは2番目のownerDianeを出力します。最初の例では?

22
user31782

COUNT()は、通常_GROUP BY_句と組み合わされる集計関数です。

curdate()は、現在の日付を出力する日付関数です。

(私が知る限り)MySQLだけが、_GROUP BY_句を使用せずにこの構文を許可します。指定しなかったため、COUNT(*)はテーブル内の行の総数をカウントし、owner列はランダムに/オプティマイザーのデフォルト/インデックスによって選択されます。

これはあなたの質問でなければなりません:

_select owner, count(*) 
from pet
group by owner;
_

これは、オプティマイザーにeach ownerの合計行をカウントするように指示します。

Group by句が言及されていない場合、集計関数はテーブルのデータ全体に適用されます。

EDIT:各行に適用されるカウントは、通常COUNT()では実行できず、通常は分析関数-> COUNT() OVER(PARTITION...)で使用されます。 MySQLには存在しません。他のオプションは、この追加の列に_JOIN/CORRELATED QUERY_を作成することです。

別の編集:各所有者の横にある合計数を知りたい場合は、サブクエリを使用できます。

_SELECT owner,
       (SELECT COUNT(*) FROM pet) as cnt
FROM pet
_
57
sagi

これは、このページの下部にあるシナリオとまったく同じように見えます: MySQLドキュメント:4.3.4.8行のカウント

ONLY_FULL_GROUP_BYが有効になっていない場合、クエリはすべての行を単一のグループとして扱うことによって処理されますが、名前付き列ごとに選択される値は不確定です。サーバーは、任意の行から値を自由に選択できます。

mysql> SET sql_mode = '';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT owner, COUNT(*) FROM pet;
+--------+----------+
| owner  | COUNT(*) |
+--------+----------+
| Harold |        8 |
+--------+----------+
1 row in set (0.00 sec)

この場合はonly_full_group_byが設定されていません。

8
P.Salmon

MySQLだけがこの種のクエリを実行できるようにします。

GROUP BY句では、集計関数と結合されていないすべての列を常に指定する必要があります。そうでない場合、データは1つの行に結合され、集計された列が正しく設定され、他のすべての列がランダムに、またはインデックスで選択されます。

だからあなたはこれが必要です:

SELECT owner, count(*) FROM pet GROUP BY owner;

結果は次のようになります。

Saknan Khan |  1
Diane       |  1

これはあなたが達成しようとしていたことですか?

または多分あなたはこれをやろうとしました:

SELECT t.owner,
       COUNT(*) as cnt
FROM pet t
CROSS JOIN pet s
GROUP BY t.owner

これにより、各所有者の横に合計数の列が追加されます。

4
Yossi

最後のクエリはOracleでは無効です:ORA-00937:単一グループ関数ではありません。これは、GROUPBY句が必要であることを意味します。 MySqlの実装に抜け穴が見つかりました。実稼働システムではこのようなクエリに依存しないでください。MySqlの次のバージョンでは、これが機能しない可能性があります。

2
Roland

ほとんどのDBMSシステムでは、group byのない追加の列を持つcount()のような集計関数は許可されません。理由があります。 DBMSは、グループ化する列を認識していません:-)。

解決策は、次のように、所有者列でクエリをグループ化することです。

SELECT owner, count(*) FROM pet GROUP BY owner;
2
Nicolai Ehemann

Count(*)集計関数は、1つの値、つまり合計行数のみを返します。そしてcurdate()関数は、システムの現在の日付を提供するだけです。

2
LazyCoder_13

はい、これは通常、groupby句を使用せずに発生します。

http://www.w3schools.com/sql/sql_groupby.asp groupby句に関するすべてのリンクを読む必要があります。

すべての列は、集計またはグループ化のいずれかで言及する必要があります

0
infectious