1

一部のレポートでは、このようなものを考慮して、極端に低い値と高い値を削除する必要があります。

SELECT ...
FROM
(
  SELECT val, ntile(10) OVER(ORDER BY val) AS tile FROM table
) AS tiled_table
WHERE tile > 1 AND tile < 10

テーブル名と列名を取得し、文字列を連結してクエリを実行するストアドプロシージャに抽出できますが、別のクエリの結果に対してこのプロシージャを使用する必要がある場合があります。PostgreSQLでそれを行う方法はありますか?

4

3 に答える 3

1

常に同じ列のセットを返す場合は、テーブルと列の名前を渡すセットを返す関数を作成できます。これは、テーブルのように使用できます。

create or replace function get_values(tablename text, columnname text)
  returns table (id integer, foobar text)
as
$$
BEGIN
  RETURN QUERY EXECUTE 'select id, '||columname||' as foobar from '||tablename;
END;
$$
language plpgsql;

次に、値が必要なときはいつでも、次を使用します。

select v.*,
       t.foobar
from get_values('table_1', 'some_column') v
  join table_2 t on ...

クエリが必要なたびに異なる数の列を返す場合、これは機能しません。

于 2012-10-25T15:04:29.833 に答える
1

この問題を解決するには、動的 SQL が必要です。一般に、クエリで動的テーブル名を使用することはできません。動的 SQL については、http: //www.postgresql.org/docs/9.2/static/ecpg-dynamic.html を参照してください。

クエリを次のように作成する場合:

FROM
(
  SELECT val, ntile(10) OVER(ORDER BY val) AS tile FROM <subquery> t
) AS tiled_table

サブクエリが括弧で囲まれている場合、これは機能します。元のクエリにない場合は、括弧を追加できます。

于 2012-10-25T14:56:50.517 に答える
0

関数を使用してクエリからの結果セットを処理する場合、最適なオプションはSELECT ... INTO TEMPORARY TABLE、一時テーブル名を使用して関数を呼び出すことです。

些細な行セットを生成する方法を考えると、PostgreSQL 関数で行セットを使用するのは厄介なほど困難です。私が知っている唯一の方法は、refcursor を使用するか、一時テーブルを処理するか、集計関数またはウィンドウ関数を実装することです。後者の 2 つのオプションでは、返される行数を制御できないため、目的には適していません。

関数は、関数を呼び出す CTE の共通テーブル式エイリアスを参照できないため、CTE を使用して仮想テーブルを作成し、テーブルの名前を関数に渡すことはできません。動作しないことを示す例:

CREATE OR REPLACE FUNCTION dynsql(tname text, colname text) RETURNS SETOF RECORD AS 
$$
BEGIN
  RETURN QUERY EXECUTE format('SELECT %I FROM %I', colname, tname);
END;
$$ LANGUAGE plpgsql;

WITH dummy(col) AS (VALUES (1),(2),(3))
SELECT * FROM dynsql('dummy','col') t(id integer);

結果:

ERROR:  relation "dummy" does not exist

...式のエイリアスはWITH式に対してローカルであるためWITHです。(関数から参照できると便利ですが、そうすると、あらゆる種類の刺激的な名前衝突の問題や、SECURITY DEFINER関数に関するセキュリティの問題が発生します。)

refcursor を使用する PL/PgSQL 関数を作成することはできますが、これにはDECLAREクエリを使用してカーソルを作成し、それを関数に渡す必要があります。通常の関数呼び出し構文をそのまま使用することはできません。また、非常に非効率的でありLOOP、関数に ing が必要です。あまり役に立たないと思います。

関数を実装するときはEXECUTE format(...) USING ...、動的 SQL をあまりひどくしないようにするために使用します。この以前の回答を参照してください。

于 2012-10-26T00:10:11.360 に答える