25

MS SQL Server 2005 用に記述された SQL クエリを Postgres 9.1 に移行する必要があります。このクエリで
代用する最良の方法は何ですか?CROSS APPLY

SELECT *
FROM V_CitizenVersions         
CROSS APPLY     
       dbo.GetCitizenRecModified(Citizen, LastName, FirstName, MiddleName,
BirthYear, BirthMonth, BirthDay, ..... ) -- lots of params

GetCitizenRecModified()function はテーブル値関数です。この関数のコードを配置することはできません。なぜなら、この関数は非常に巨大で、計算が難しく、放棄できないからです。

4

4 に答える 4

34

Postgres 9.3以降では、LATERAL結合を使用します。

SELECT v.col_a, v.col_b, f.*  -- no parentheses, f is a table alias
FROM   v_citizenversions v
LEFT   JOIN LATERAL f_citizen_rec_modified(v.col1, v.col2) f ON true
WHERE  f.col_c = _col_c;

なぜLEFT JOIN LATERAL ... ON trueですか?


古いバージョンの場合、セットを返す関数 (またはOR )を使用して、あなたがしようとしていること達成するための非常に簡単な方法があります。RETURNS TABLERETURNS SETOF recordRETURNS record

SELECT *, (f_citizen_rec_modified(col1, col2)).*
FROM   v_citizenversions v

この関数は、外側のクエリの行ごとに 1 回値を計算します。関数が複数の行を返す場合、結果の行はそれに応じて乗算されます。行型を分解するには、構文上すべての括弧が必要です。テーブル関数は次のようになります。

CREATE OR REPLACE FUNCTION f_citizen_rec_modified(_col1 int, _col2 text)
  RETURNS TABLE(col_c integer, col_d text)
  LANGUAGE sql AS
$func$
SELECT s.col_c, s.col_d
FROM   some_tbl s
WHERE  s.col_a = $1
AND    s.col_b = $2
$func$;

WHERE列が同じレベルで表示されないため、句を適用する場合は、これをサブクエリまたは CTE でラップする必要があります。(関数の出力列ごとに評価が繰り返されるのを防ぐため、とにかくパフォーマンスが向上します):

SELECT col_a, col_b, (f_row).*
FROM  (
   SELECT col_a, col_b, f_citizen_rec_modified(col1, col2) AS f_row
   FROM   v_citizenversions v
   ) x
WHERE (f_row).col_c = _col_c;

これまたは同様のことを行うには、他にもいくつかの方法があります。それはすべて、あなたが正確に何を望んでいるかによって異なります。

于 2012-07-13T15:22:19.560 に答える
22

ネクロマンシング:
PostgreSQL 9.3 の新機能:

LATERAL キーワード

左 | 左 | 右 | 内部 JOIN LATERAL

INNER JOIN LATERALと同じですCROSS APPLY
LEFT JOIN LATERAL同じですOUTER APPLY

使用例:

SELECT * FROM T_Contacts 

--LEFT JOIN T_MAP_Contacts_Ref_OrganisationalUnit ON MAP_CTCOU_CT_UID = T_Contacts.CT_UID AND MAP_CTCOU_SoftDeleteStatus = 1 
--WHERE T_MAP_Contacts_Ref_OrganisationalUnit.MAP_CTCOU_UID IS NULL -- 989


LEFT JOIN LATERAL 
(
    SELECT 
         --MAP_CTCOU_UID    
         MAP_CTCOU_CT_UID   
        ,MAP_CTCOU_COU_UID  
        ,MAP_CTCOU_DateFrom 
        ,MAP_CTCOU_DateTo   
   FROM T_MAP_Contacts_Ref_OrganisationalUnit 
   WHERE MAP_CTCOU_SoftDeleteStatus = 1 
   AND MAP_CTCOU_CT_UID = T_Contacts.CT_UID 

    /*  
    AND 
    ( 
        (__in_DateFrom <= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateTo) 
        AND 
        (__in_DateTo >= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateFrom) 
    ) 
    */
   ORDER BY MAP_CTCOU_DateFrom 
   LIMIT 1 
) AS FirstOE 
于 2016-03-08T16:49:48.170 に答える
1

このリンクは、Postgres 9.0+ でそれを行う方法を示しているようです。

PostgreSQL: 再帰的な CTE のパラメータ化

これは、「セットを返す関数を使用して CROSS APPLY をエミュレートする」というタイトルのセクションのページのさらに下にあります。例の後に制限のリストがあることに注意してください。

于 2012-07-13T15:19:02.520 に答える