SQL-Group Byでのエイリアスの使用


143

SQL構文に興味があるだけです。だから私が持っているなら

SELECT 
 itemName as ItemName,
 substring(itemName, 1,1) as FirstLetter,
 Count(itemName)
FROM table1
GROUP BY itemName, FirstLetter

これは間違っているでしょう

GROUP BY itemName, FirstLetter 

本当にあるべき

GROUP BY itemName, substring(itemName, 1,1)

しかし、なぜ前者を便宜上使用できないのでしょうか。


13
Postgresqlで許可されています
Michael Buen

7
MySQLでも可能
Kip

1
どのrdbmsについて話しているのですか?
Shiwangini、

回答:


292

SQLは、クエリが次の順序で実行されたかのように実装されます。

  1. FROM句
  2. WHERE句
  3. GROUP BY句
  4. HAVING句
  5. SELECT句
  6. ORDER BY句

ほとんどのリレーショナルデータベースシステムでは、この順序は、前のステップで導入されている必要があるため、有効な名前(列またはエイリアス)を説明しています。

したがって、OracleおよびSQL Serverでは、SELECT句の前にGROUP BYが実行されるため、SELECT句で定義したGROUP BY句で用語を使用できません。

ただし、例外もあります。MySQLとPostgresには、それを可能にする高度な機能があるようです。


3
この説明が好きです。構文糖としてエンジンに追加するのがどれほど難しいかは推測できません。
Haoest

11
DBが同じ式を実現するのに十分スマートである場合、式を再評価せずにSELECT句とGROUP BY句内にあるかどうかはわかりますか?つまり、がある場合GROUP BY substring(itemName, 1,1)、データベースは、SELECT句で部分文字列を再計算するパフォーマンスヒットを受け取らないほどスマートですか?
キップ

10
グループ化されたクエリのSELECT句では、GROUP BY式と集計値にのみアクセスできます。つまり、スマートであることではありません。グループ化が機能するには、この方法で実装する必要があります。(そしてそれはSQL標準で要求されています)。しかし、より些細なケース(たとえば、WHEREとSELECT句の同じ式)の場合でも、最先端のデータベースシステムはそれを1回だけ計算します。この最適化は、共通部分式の除去と呼ばます。
Codo 2013

6
実行順序は質問とどのような関係がありますか?質問者がCOUNT()でGROUP BYを試みていたのとは異なります。実際、尋ねられたクエリは、コメントで指摘されているように、MySQLおよびPostgreSQLでうまく機能します。

1
mysqlの場合、ビットマスクにONLY_FULL_GROUP_BYが含まれてsql_modeいないため、オプティマイザーは、句でエイリアスをさまざまに/ 異なる方法で使用することで、より良い結果を提供する可能性があります。HAVING
2016

28

エイリアスを使用できるように、常にサブクエリを使用できます。もちろん、パフォーマンスを確認します(dbサーバーは両方とも同じように実行されますが、確認に支障はありません)。

SELECT ItemName, FirstLetter, COUNT(ItemName)
FROM (
    SELECT ItemName, SUBSTRING(ItemName, 1, 1) AS FirstLetter
    FROM table1
    ) ItemNames
GROUP BY ItemName, FirstLetter

2
パフォーマンスが悪いため、サブクエリは可能な限り避けてください。関数のコピーを使用すると、データベースオプティマイザーによって検出され、1回だけ実行されるため、はるかに優れています。
Roland

1
@Rolandですが、その場合の実行計画に違いはありません。他にパフォーマンスに関する考慮事項はありますか?
グイド・モカ

@Roland、相関サブクエリ、またはループや行ごとの動作につながるその他の構文は回避する必要があります。ネストされたサブクエリをどの程度深く掘り下げるかには制限がありますが、サブクエリがリードすることは一般的には当てはまりません悪いパフォーマンスに。この場合、Chrisが言ったように、実行プラン(別名クエリプラン、説明プラン)をサブクエリありとなしの両方で比較して、実際に違いがあるかどうかを確認できます。ほとんどすべてのデータベースエンジンがクエリを書き換えるので、実行する内容を完全に制御することはできません。それが宣言型構文のポイントです。
ダボス

16

少なくともPostgreSQLでは、GROUP BY句の結果セットの列番号を使用できます。

SELECT 
 itemName as ItemName,
 substring(itemName, 1,1) as FirstLetter,
 Count(itemName)
FROM table1
GROUP BY 1, 2

もちろん、これをインタラクティブに実行し、クエリを編集して結果の列の数または順序を変更すると、これは面倒になります。それでも。


GROUP BY FirstLetterPostgresqlでは許可されています。つまり、これをPostgresqlで実行してみます。tnameによってinformation_schema.tablesグループからsubstring(table_name、1,2)をtnameとして選択します
Michael Buen

1
@MichaelBuenは私にとって潜在的に問題があるようです。簡単なテストから、同じ名前のエイリアスとベーステーブル列がある場合、後者が優先されるように見えますか?SQL Fiddle。したがって、エイリアスによってこのグループに依存している場合、後でスキーマを変更すると、暗黙のうちにクエリが中断され、セマンティクスが変更される可能性があります。
マーティン・スミス

@MartinSmithは、それが落とし穴であることを知っただけなので、使用を控えます。PostgreSQLがそのショートカットを許可していることを考えると、エイリアスに優先順位を付ける必要があります。そうでない場合、そのショートカットはまったく許可されません。
Michael Buen 2014年

これはPostgreSQLデザイナーによるひどい考えでした。GROUP BY「明らかに」機能しない、集約関数またはウィンドウ関数を含む式を試そうとすると、混乱を招きます。
Lukas Eder 2017

13

SQL Serverでは、処理の論理的な順序のため、GROUP BY句でエイリアスを参照することはできません。GROUP BY句はSELECT句の前に処理されるため、GROUP BY句が評価されるときにエイリアスは不明です。これは、ORDER BY句でエイリアスを使用できる理由も説明しています。

ここに、SQL Serverの論理処理フェーズに関する情報の1つのソースがあります


8

なぜそうなのかは答えていませんが、SQL Serverでこの制限を回避する方法を示しCROSS APPLY、エイリアスの作成に使用しただけです。次にGROUP BY、次のように句で使用します。

SELECT 
 itemName as ItemName,
 FirstLetter,
 Count(itemName)
FROM table1
CROSS APPLY (SELECT substring(itemName, 1,1) as FirstLetter) Alias
GROUP BY itemName, FirstLetter

4

Group By(postgresなど、それをサポートするサービス)でエイリアスを使用すると、意図しない結果になる可能性があることに注意してください。たとえば、内部ステートメントに既に存在するエイリアスを作成する場合、Group Byは内部フィールド名を選択します。

-- Working example in postgres
select col1 as col1_1, avg(col3) as col2_1
from
    (select gender as col1, maritalstatus as col2, 
    yearlyincome as col3 from customer) as layer_1
group by col1_1;

-- Failing example in postgres
select col2 as col1, avg(col3)
from
    (select gender as col1, maritalstatus as col2,
    yearlyincome as col3 from customer) as layer_1
group by col1;

3

一部のDBMSでは、式全体を繰り返す必要がなく、エイリアスを使用できます。
Teradataはそのような例の1つです。

文書化された理由により、ビルが推奨する序数表記は避けます このSOの質問にます。

簡単で堅牢な代替手段は、常にGROUP BY句で式を繰り返すことです。
DRYはSQLには適用されません。


1

SQLiteのビューからの結果をグループ化するときは、エイリアスの使用に注意してください。エイリアス名が(ビューに対して)基になるテーブルの列名と同じである場合、予期しない結果になります。


0

昔、Oracleでサポートされていた以前のDEC製品であるRdbによって、列のエイリアスをGROUP BYで使用できることがわかりました。バージョン11までの主流のOracleでは、列のエイリアスをGROUP BYで使用することはできません。Postgresql、SQL Server、MySQLなどで許可されているものと許可されていないものがあります。YMMV。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.