1

複数行の副選択は、句のin演算子の右側で使用されます。where

create table t (a integer);
insert into t (a) values (1), (9);

drop function if exists f();

create function f()
returns void as $$
begin
execute '
    select a
    from t
    where a in $1
' using (select 1 union select 2);
end;$$
language plpgsql;

select f();

ERROR:  more than one row returned by a subquery used as an expression
CONTEXT:  SQL statement "SELECT (select 1 union select 2)"
PL/pgSQL function "f" line 3 at EXECUTE statement

上記の機能が機能した場合、どのように達成するのですか?

4

2 に答える 2

3

あなたの質問には、これ以上簡単に解決できないものは何もありません。

SELECT a
FROM   t
JOIN  (VALUES (1), (2)) x(a) USING (a); -- any query returning multiple int

あなたの例で必要性を明確にできますか?


概念実証として、これはより単純で高速です。

CREATE OR REPLACE FUNCTION x.f1()
  RETURNS SETOF integer AS
$BODY$
BEGIN
RETURN QUERY EXECUTE '
    SELECT a
    FROM t
    WHERE a = ANY($1)'
USING ARRAY(VALUES (1), (2)); -- any query here
END;
$BODY$
LANGUAGE plpgsql;

IN()および= ANY()のパフォーマンス

あなたの観察は的確です。そしてそれには理由があります。試す:

EXPLAIN ANALYZE SELECT * FROM tbl WHERE id IN (1,2,3);

クエリプランは次のことを明らかにします。

インデックス条件:(id = ANY('{1,2,3}' :: integer []))

PostgreSQLはid IN (..)構造をid = ANY(..)内部的に変換します。これら2つは同じように機能しますが、オーバーヘッドのペナルティはごくわずかです。

私のコードは、あなたが診断したとおりに、ステートメントを作成するのが速いだけです。

于 2012-03-21T18:40:37.820 に答える
0
create function f()
returns setof integer as $$
begin
return query execute format('
    select a
    from t
    where a in %s
', replace(replace(array(select 1 union select 2)::text, '{', '('), '}', ')'));
end$$
language plpgsql;
于 2012-03-21T17:47:20.700 に答える