私はPostgreSQLを初めて使用し、SQLServerからクエリを変換しようとしています。
とりわけ、bUsrActive、bUsrAdmin、およびsUsrClientCode列を持つUsersテーブルがあります。同じsUsrClientCode(bUsrAdmin = trueおよびbUsrActive = true)を持つ別のユーザーが存在しない場合は、Usersを更新し、bUsrActive = falseに設定します。
SQLServerではこのクエリがあります
UPDATE u SET u.bUsrActive = 0
FROM Users u
LEFT JOIN Users u2 ON u.sUsrClientCode = u2.sUsrClientCode AND u2.bUsrAdmin = 1 AND u2.bUsrActive = 1
WHERE u.bUsrAdmin = 0 AND u.bUsrActive = 1 AND u2.nkUsr IS NULL
これをpostgresに変換しようとしています。私は3つのアプローチを書きました。
1)私の最初の試み。明らかに機能していません。
UPDATE Users u
SET bUsrActive = false
FROM Users u2
WHERE u.sUsrClientCode = u2.sUsrClientCode AND u2.bUsrAdmin = true AND u2.bUsrActive = true
AND u.bUsrAdmin = false AND u.bUsrActive = true AND u2.nkUsr IS NULL;
2)それが機能しない理由を理解しています(すべてのユーザーを更新します)。 UPDATE ... SET部分でテーブルUsersuを参照する方法がわかりません。
UPDATE Users
SET bUsrActive = false
FROM Users u
LEFT JOIN Users u2 ON u.sUsrClientCode = u2.sUsrClientCode AND u2.bUsrAdmin = true AND u2.bUsrActive = true
WHERE u.bUsrAdmin = false AND u.bUsrActive = true AND u2.nkUsr IS NULL;
3)以下は機能していますが、結合を使用していません。
UPDATE Users
SET bUsrActive = false
WHERE NOT EXISTS (
SELECT 1
FROM Users u
WHERE u.sUsrClientCode = Users.sUsrClientCode AND u.bUsrAdmin = true AND u.bUsrActive = true
) AND Users.bUsrAdmin = false AND Users.bUsrActive = true;
私はおそらく最後の解決策に行きます。左結合を使用してやりたいことができるかどうかを知りたかっただけです。
この更新クエリをSQLサーバー形式からPostgreSQLに変換する一般的な方法は次のとおりです。
UPDATE Users
SET bUsrActive = false
WHERE
ctid IN (
SELECT u.ctid FROM Users u
LEFT JOIN Users u2 ON u.sUsrClientCode = u2.sUsrClientCode AND u2.bUsrAdmin = 1 AND u2.bUsrActive = 1
WHERE u.bUsrAdmin = 0 AND u.bUsrActive = 1 AND u2.nkUsr IS NULL
)
ctid は、行の一意の場所を指す疑似列です。代わりに、テーブルの主キーがあればそれを使用できます。
更新されたテーブルUsers
がFROM句の同じテーブルUsers u
に結合されることはないため、質問のクエリ#2は期待どおりに機能しません。 FROM句にテーブル名を2回入力した場合と同様に、テーブル名は暗黙的に結合またはバインドされないため、2つの独立した行のセットと見なされます。
これが正しい方法だと思います。2)サブ選択を行うよりも最適で効率的だと思います。
UPDATE Users uOrig
SET bUsrActive = false
FROM Users u
LEFT JOIN Users u2 ON u.sUsrClientCode = u2.sUsrClientCode AND u2.bUsrAdmin = 1 AND u2.bUsrActive = 1
WHERE u.bUsrAdmin = 0 AND u.bUsrActive = 1 AND u2.nkUsr IS NULL
and uOrig.sUsrClientCode = u.sUsrClientCode;