3

次の集計関数があると仮定します。

  • AGG1
  • AGG2
  • AGG3
  • AGG4

次のように有効な SQL を (db にとらわれない方法で) 書くことは可能ですか?

SELECT [COL1, COL2 ....], AGG1(param1), AGG2(param2) FROM [SOME TABLES]
WHERE [SOME CRITERIA]
HAVING AGG3(param2) >-1 and AGG4(param4) < 123
GROUP BY COL1, COL2, ... COLN
ORDER BY COL1, COLN ASC
LIMIT 10

ここで、COL1 ... COLN はクエリ対象のテーブル内の列であり、param1 ... paramX は AGG 関数に渡されるパラメーターです。

注: AGG1 と AGG2 は列として結果に返されます (ただし、HAVING CLAUSE には表示されず、AGG3 と AGG4 は HAVING CLAUSE に表示されますが、結果セットには返されません。

理想的には、ソリューションに対する DB にとらわれない回答が必要ですが、DB に縛られる必要がある場合は、PostgreSQL (v9.x) を使用しています。

編集

明確にするために、クエリで GROUP BY を使用することに反対しているわけではありません。私の SQL はあまり良くないので、上記の SQL の例は少し誤解を招く可能性があります。上記の疑似 sql ステートメントを編集して、私の意図をより明確にすることを願っています。

私が知りたかった主なことは、AGG 関数を使用した選択クエリが次のことができるかどうかでした。

  • HAVING 句で指定せずに、返された列に集計関数の値を含めます。
  • HAVING 句に集計関数が指定されていますが、結果セットには返されません。

私がこれまでに受け取った回答からすると、両方の質問に対する答えはイエスのようです。SQL を修正するために私がしなければならない唯一のことは、返される行が一意であることを確認するために GROUP BY 句を追加することです。

4

3 に答える 3

1

GROUP BY を使用せずに列を集計する唯一の方法は、ウィンドウ関数を使用することです。問題の詳細を省略しましたが、以下が探している可能性があります。

SELECT *
FROM (
    SELECT [COL1, COL2 ....], 
           AGG1(param1) over (partition by some_grouping_column) as agg1, 
           AGG2(param2) over (partition by some_grouping_column) as agg2,
           row_number() over () as rn
    FROM [SOME TABLES]
    WHERE [SOME CRITERIA]
    ORDER BY COL1
)  t
WHERE AGG3 >-1 
  AND AGG4 < 123
  AND rn <= 10
ORDER BY col1

これは標準の ANSI SQL であり、PostgreSQL (8.4 以降) を含むほとんどのデータベースで動作します。

partition by 句の両方の集計に同じグループ化列を使用する必要はないことに注意してください。

ANSI SQL に固執したい場合は、row_number()関数を使用して結果を制限する必要があります。これを PostgreSQL (または何らかの方法でサポートする他の DBMS) でのみ実行する場合はLIMIT、LIMIT 原因を派生テーブル (内部クエリ) に移動します。

于 2011-10-24T07:00:54.120 に答える
1

PostgreSQL のメジャー バージョンには、ドットの後の最初の数字が含まれているため、「PostgreSQL (v9.x)」は十分に具体的ではありません。@kekekela が言ったように、完全にデータベースに依存しない (安価な) 方法はありません。PostgreSQL 9.0 と 9.1 の間でも、重要な構文上の違いがあります。

グループ化された値しかない場合は、明示的な句AGG1(param1), AGG2(param2)を提供せずに逃げることができます。GROUP BYグループ化された列とグループ化されていない列を混在させるためGROUP BYSELECT. これは、PostgreSQL のどのバージョンにも当てはまります。GROUP BY と HAVING については、マニュアルを参照してください。

ただし、バージョン9.1以降では、 に主キーをリストするGROUP BYと、このテーブルの追加の列をスキップして、引き続きSELECTリストで使用できます。バージョン 9.1のリリース ノートには次のように記載されてい ます。

GROUP BY 句で主キーが指定されている場合、クエリ対象リストで非 GROUP BY 列を許可します。 (Peter Eisentraut)

パラメータについて

集計関数に定数値を入力するつもりですか? ポイントは何ですか?ドキュメントは私たちに教えてくれます

集計関数は、複数の入力行から 1 つの結果を計算します。

それとも、これらのパラメーターを列名にしたいですか? この種の動的 SQL は、データベースにコミットする前にステートメントが生成される限り機能します。sql準備済みステートメントまたは単純な関数または関数では機能しませんplpgsql。そのためには、関数でEXECUTEを使用する必要があります。plpgsql

SQLi に対する安全策として、にはUSING $1, $2構文を使用し、列またはテーブル名にはquote_ident()を使用します。

于 2011-10-24T03:24:23.487 に答える
0

これは、GROUP BYステートメントでCOL1、COL2などが必要になる場合を除いて、高レベルの観点から機能するはずです。そうでない場合、SELECTリストでは有効になりません。SELECTリストにAGG1などがあり、HAVINGにはないことは問題ではありません。

dbにとらわれない限り、何をするにしても構文を微調整する必要があります(たとえば、私の頭の中で知っているPostgreSQL、SQL SERVER、OracleではLIMITが異なります)が、高レベルの表現がしっかりしていれば、それぞれのステートメントを適切に構築するためのロジックを構築できます。

于 2011-10-23T23:54:09.803 に答える