MS SQL Server 2005用に書かれたSQLクエリをPostgres 9.1に移行する必要があります。
このクエリでCROSS APPLY
を代用する最良の方法は何ですか?Postgres analogueとSQL ServerのCROSS APPLYに適用
GetCitizenRecModified()
関数はテーブル値関数です。私はこの関数のコードを置くことはできません。なぜなら、実際には膨大で、計算が難しく、放棄できないからです。
MS SQL Server 2005用に書かれたSQLクエリをPostgres 9.1に移行する必要があります。
このクエリでCROSS APPLY
を代用する最良の方法は何ですか?Postgres analogueとSQL ServerのCROSS APPLYに適用
GetCitizenRecModified()
関数はテーブル値関数です。私はこの関数のコードを置くことはできません。なぜなら、実際には膨大で、計算が難しく、放棄できないからです。
参加:
SELECT v.col_a, v.col_b, f.* -- no parentheses here, 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
? 古いバージョンについては
、私はあなたが集合を返す関数(RETURNS TABLE
or RETURNS SETOF record
OR RETURNS record
)にしようとしているどう思うか達成する非常に単純な方法があります:
SELECT *, (f_citizen_rec_modified(col1, col2)).*
FROM v_citizenversions v
この関数は、外部クエリのすべての行に対してnceを返します。関数が複数の行を返す場合、結果の行はそれに応じて乗算されます。すべて小文字は、行タイプを分解するために構文的に必要です。あなたは列が同じレベルに表示されていないので、WHERE
句を適用したい場合は、サブクエリまたはCTEでこれをラップする必要が
CREATE OR REPLACE FUNCTION f_citizen_rec_modified(_col1 int, _col2 text)
RETURNS TABLE(col_c integer, col_d text) AS
$func$
SELECT s.col_c, s.col_d
FROM some_tbl s
WHERE s.col_a = $1
AND s.col_b = $2
$func$ LANGUAGE sql;
:表関数は、次のようなものを見ることができます。 (あなたは、関数のすべての出力列の評価を繰り返し防ぐため、そしてそれは、とにかくパフォーマンスのために良いでしょう):このまたは類似した何かをするには、いくつかの他の方法があります
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;
。それはすべてあなたが正確にしたいものに依存します。
あなたが提案したクエリを使用しました。今私はショックを受けている:クエリは1分以上実行されます。 ms SQLでは秒未満のO_Oしかかかりません。 – user1178399
@ user1178399:多くの要素を知らなくても、それについてコメントすることは事実上不可能です。私は、パフォーマンスを改善できると推測します。 –
このリンクは、Postgresの9.0以降でそれを行う方法を示すために表示されます。
PostgreSQL: parameterizing a recursive CTE
それは「エミュレートCROSSは、集合を返す関数で適用する」というタイトルのセクション内のページのさらに下です。例の後に制限のリストを書き留めておいてください。 Postgresの9.3以降LATERAL
を使用して
私はしかし、私はパフォーマンスの問題を発見したアーウィンBrandstetterの答えが好き:
SELECT *, (f_citizen_rec_modified(col1, col2)).*
FROM v_citizenversions v
を実行しているときf_citizen_rec_modified関数は(v_citizenversions内のすべての行を乗じた)が返すすべての列のために1時間を走ったことになります。私はこの効果のためのドキュメントを見つけられませんでしたが、デバッグによってそれを推論することができました。ここで問題になるのは、このパフォーマンスを悪用する副作用なしに、どのようにしてこの効果を得ることができるか(9.3より前の側面結合)
更新:私は答えを見つけたようです。次のようにクエリを書き直す:
select x.col1, x.col2, x.col3, (x.func).*
FROM (select SELECT v.col1, v.col2, v.col3, f_citizen_rec_modified(col1, col2) func
FROM v_citizenversions v) x
、別の列に胸像もの結果て選択することを包む鍵差最初生関数の結果を取得すること(内部サブクエリ)。 PostgreSQLの9.3で
新:これはPG 9.2
Necromancing上でテストされました
LATERALキーワード左
|右|あなたは、クロスがPostgresのでは適用する必要はありません
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
:インナーはLATERAL
INNER JOIN LATERAL
がCROSS APPLY
と
LEFT JOIN LATERAL
と同じであり、JOINはOUTER APPLY
使用例と同じです。関数のようにテーブル関数を使うことができます。単にそれらに参加してください。 –
@a_horse_with_no_name - 「CROSS APPLY」は、一度実行してから結果を結合するのではなく、相関パラメータでTVFを再実行します。 –