SELECTステートメントに1つの集約関数がある場合、ステートメントの他のすべての値は集約関数であるか、GROUP BY句にリストされている必要があります。わかりませんなぜそれが事実です。
私が行った場合:
SELECT Name, 'Jones' AS Surname FROM People
私は得ます:
NAME SURNAME
Dave Jones
Susan Jones
Amy Jones
そのため、DBMSは各行から値を取得し、結果セットでそれに単一の値を追加しました。それはいいです。しかし、それがうまくいくなら、なぜ私はできないのですか?
SELECT Name, COUNT(Name) AS Surname FROM People
同じように見えますが、各行から値を取得し、単一の値を追加します。しかし、代わりに:
NAME SURNAME
Dave 3
Susan 3
Amy 3
私は得ます:
集計関数の一部として指定された式 'ContactName'を含まないクエリを実行しようとしました。
許可されていないことはわかっていますが、2つの状況が似ているため、理由がわかりません。 DBMSを実装しやすくするためですか?なぜだと思うように動かないのか、誰かに説明してもらえたら、ありがたいです。
集計は完全な結果では機能せず、結果のグループでのみ機能します。
以下を含むテーブルを考えてみましょう:
_Person Pet
-------- --------
Amy Cat
Amy Dog
Amy Canary
Dave Dog
Susan Snake
Susan Spider
_
Personでグループ化するクエリを使用すると、データが次のグループに分割されます。
_Amy:
Amy Cat
Amy Dog
Amy Canary
Dave:
Dave Dog
Susan:
Susan Snake
Susan Spider
_
集計を使用する場合、たとえばcount集計では、グループごとに1つの結果が生成されます。
_Amy:
Amy Cat
Amy Dog
Amy Canary count(*) = 3
Dave:
Dave Dog count(*) = 1
Susan:
Susan Snake
Susan Spider count(*) = 2
_
したがって、クエリselect Person, count(*) from People group by Person
は、グループごとに1つのレコードを提供します。
_Amy 3
Dave 1
Susan 2
_
結果でペットフィールドも取得しようとすると、各グループのそのフィールドに複数の値が存在する可能性があるため、機能しません。
(MySQLのような一部のデータベースは、とにかくそれを許可し、グループ内からランダムな値を返すだけであり、結果が適切かどうかを知るのはあなたの責任です。)
集計を使用してもグループ化を指定しない場合でも、クエリはグループ化され、結果全体が単一のグループになります。したがって、クエリselect count(*) from Person
はすべてのレコードを含む単一のグループを作成し、集計はそのグループのレコードをカウントできます。結果には各グループの1行が含まれます。グループが1つしかないため、結果には1行が含まれます。
グループ化せずにCOUNTを呼び出すと、テーブルが1つのグループに「折りたたまれ」、select句のグループ内の個々の項目にアクセスできなくなります。
それでも、サブクエリまたはクロス結合を使用して結果を取得できます。
SELECT p1.Name, COUNT(p2.Name) AS Surname FROM People p1 CROSS JOIN People p2 GROUP BY p1.Name
SELECT Name, (SELECT COUNT(Name) FROM People) AS Surname FROM People
他の人が説明したように、_GROUP BY
_がある場合、またはSELECT
リストでCOUNT()
などの集計関数を使用している場合は、行のグループ化を行っているため、一致する行が折りたたまれていますグループごとに1つに。
_GROUP BY
_なしでSELECT
リストで集計関数のみを使用する場合、_GROUP BY 1
_があると考えて、すべての行がグループ化され、1つに折りたたまれます。したがって、100行ある場合、100行あるため、データベースは実際に名前を表示できません。
ただし、「ウィンドウ処理」機能を持つRDBMSの場合、必要なことは実行可能です。例えば。 _GROUP BY
_なしで集約関数を使用します。
テーブル内のすべての行(名前)がカウントされるSQL-Serverの例:
_SELECT Name
, COUNT(*) OVER() AS cnt
FROM People
_
上記はどのように機能しますか?
COUNT(*) OVER() AS cnt
が存在しなかったようなName
が表示され、
テーブルを完全にグループ化しているようにCOUNT(*)
を表示します。
もう一つの例。テーブルにSurname
フィールドがある場合は、次のようにして、姓でグループ化されたすべての行を表示し、同じ姓を持つ人の数を数えることができます。
_SELECT Name
, Surname
, COUNT(*) OVER(PARTITION BY Surname) AS cnt
FROM People
_
クエリは暗黙的に結果セットにさまざまなタイプの行を要求しますが、これは許可されていません。返されるすべての行は同じタイプで、同じ種類の列を持つ必要があります。
'SELECT name、surname'は、テーブルのすべての行の行を返したいと考えています。
'SELECT COUNT(*)'は、テーブル内のすべての行の結果を組み合わせた単一の行を返したいと考えています。
この場合、データベースはおそらく両方のクエリを実行してから、 'SELECT COUNT(*)'の結果をすべての結果にコピーすることができます。これを行わない理由の1つは、ステルスパフォーマンスヒットになることです。どこにも宣言せずに、追加の自己結合を効果的に実行することになります。
他の回答では、このクエリの実際のバージョンを作成する方法を説明しているため、ここでは説明しません。
集計関数とgroup by句は別個のものではなく、クエリの別の場所に表示される同じものの一部です。列で集計する場合は、集計に使用する関数を指定する必要があります。集計関数が必要な場合は、いくつかの列に適用する必要があります。
集約関数は、特定の条件を持つ複数の行から値を取得し、それらを1つの値に結合します。この条件は、ステートメントのGROUP BY
によって定義されます。したがって、GROUP BY
なしで集約関数を使用することはできません
と
SELECT Name, 'Jones' AS Surname FROM People
固定値を持つ追加の列を選択するだけです...
SELECT Name, COUNT(Name) AS Surname FROM People GROUP BY Name
名前を選択するようにDBMSに指示し、すべての名前がテーブルで発生する頻度を覚えて、それらを1行にまとめます。したがって、GROUP BY
を省略した場合、DBMSはレコードを折りたたむ方法を伝えることができません。