8

次のように、左外部結合でパラメーターを渡すストアドプロシージャを呼び出そうとしています。

select i.name,sp.*
from items i
left join compute_prices(i.id,current_date) as sp(price numeric(15,2), 
          discount numeric(5,2), taxes numeric(5,2)) on 1=1
where i.type = 404;

compute_prices()レコードのセットを返します。
これはpostgresが示すメッセージです:

エラー:テーブル「i」のFROM句エントリへの参照が無効です

...左結合compute_prices(i.id、current_date)..。

ヒント:テーブル "i"のエントリがありますが、クエリのこの部分から参照することはできません。

この種のクエリはFirebirdで機能します。クエリを使用するだけで機能させる方法はありますか?アイテムを循環し、を個別に呼び出す別のストアドプロシージャを作成したくありませんcompute_prices()

4

3 に答える 3

6

一般に、提供されている単純な構文@Danielを使用して、よく知られている行型(別名、レコード型、複合型、複合型)を拡張できます。

SELECT i.name, (compute_prices(i.id, current_date)).*
FROM   items i
WHERE  i.type = 404;

しかし、あなたの説明が正確であれば...

Compute_prices spは、一連のレコードを返します。

...匿名のレコードを扱っています。Postgresは匿名レコードを拡張する方法を知らず、絶望の中で例外をスローします。

ERROR:  a column definition list is required for functions returning "record"

PostgreSQL 9.3

Postgres9.3にはその解決策があります。、コメントで@a_horseがLATERAL述べているように:

SELECT i.name, sp.*
FROM   items i
LEFT   JOIN LATERAL compute_prices(i.id,current_date) AS sp (
                       price    numeric(15,2)
                      ,discount numeric(5,2)
                      ,taxes    numeric(5,2)
                      ) ON TRUE
WHERE i.type = 404;

マニュアルの詳細。

PostgreSQL9.2以前

物事は毛むくじゃらになります。回避策は次のとおりです。匿名レコードをよく知られたタイプに変換するラッパー関数を記述します。

CREATE OR REPLACE FUNCTION compute_prices_wrapper(int, date)
  RETURNS TABLE (
            price    numeric(15,2)
           ,discount numeric(5,2)
           ,taxes    numeric(5,2)
          ) AS
$func$
    SELECT * FROM compute_prices($1, $2)
    AS t(price    numeric(15,2)
        ,discount numeric(5,2)
        ,taxes    numeric(5,2));
$func$ LANGUAGE sql;

次に、@ Danielによる単純なソリューションを使用して、ラッパー関数をドロップするだけです。

SELECT i.name, (compute_prices_wrapper(i.id, current_date)).*
FROM   items i
WHERE  i.type = 404;

PostgreSQL8.3以前

PostgreSQL 8.3はEOLに到達したばかりで、現在(2013年2月)サポートされていません
したがって、可能であればアップグレードすることをお勧めします。しかし、できない場合:

CREATE OR REPLACE FUNCTION compute_prices_wrapper(int, date
           ,OUT price    numeric(15,2)
           ,OUT discount numeric(5,2)
           ,OUT taxes    numeric(5,2))
  RETURNS SETOF record AS
$func$
    SELECT * FROM compute_prices($1, $2)
    AS t(price    numeric(15,2)
        ,discount numeric(5,2)
        ,taxes    numeric(5,2));
$func$ LANGUAGE sql;

それ以降のバージョンでも動作します。

適切な解決策は、最初compute_prices()によく知られた型を返すように関数を修正することです。返される関数SETOF recordは通常、PITAです。私は5メートルのポールでそれらを突くだけです。

于 2013-02-08T18:53:21.663 に答える
3

関数が常に3つの価格のレコードを返すと仮定すると、compute_pricesその戻りタイプをTABLE (price numeric(15,2), discount numeric(5,2),taxes numeric(5,2))にできます。そうすると、必要なものは次のように表現できると思います。

SELECT i.name, (compute_prices(i.id,current_date)).*
  FROM items i
WHERE i.type=404;

LEFT JOIN ON 1=1制約のない通常のJOIN(またはCROSS JOIN)と変わらないように思われることに注意してください。私は、この質問を実際には左の結合とは無関係であると解釈しました。

于 2013-02-08T14:10:48.140 に答える
1

ダニエルの答えもうまくいくと思いますが、まだ試していません。ロギングと呼ばれるスキーマにlist_failed_jobs2と呼ばれるSPがあり、Dualと呼ばれるダミーテーブル(Oracleのように)があり、次のステートメントが機能することを知っています。

select * from Dual left join 
              (select * from logging.list_failed_jobs2()) q on 1=1;

SP呼び出しは、parens、correlation(q)、またはON句がないと機能しないことに注意してください。私のSPもSETOFを返します。

したがって、私はこのようなものがあなたのために働くと思います:

select i.name,sp.*
from items i
left join (select * from compute_prices(i.id,current_date)) as sp on 1=1
where i.type = 404;

お役に立てば幸いです。

于 2013-02-08T18:00:27.960 に答える