问题描述
我是PostgreSQL的新手,正尝试从SQL Server转换查询。
I'm new in PostgreSQL and trying to convert a query from SQL Server.
我有一个表Users,其中包括bUsrActive,bUsrAdmin和sUsrClientCode。我想更新用户并设置bUsrActive = false,如果不存在另一个具有相同sUsrClientCode的用户,其中bUsrAdmin = true和bUsrActive = true。
I have a table Users with, among others, the columns bUsrActive, bUsrAdmin and sUsrClientCode. I want to update Users and set bUsrActive = false if there does not exist a another user with the same sUsrClientCode where bUsrAdmin = true and bUsrActive = true.
在SQL Server中拥有此查询
In SQL Server I have this query
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种方法。
I'm trying to convert this to postgres. I wrote 3 approaches.
1)我的第一次尝试。
1) My first attempt. Obviously not working.
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部分中引用表Users u。
2) I understand why it's not working (it updates all users). I just can't figure out how can I reference table Users u in the UPDATE ... SET part.
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)以下工作正常,但未使用join。
3) The following is working, but not using join.
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;
我可能会选择最后一个解决方案。我只是想知道是否可以使用左联接来做我想做的事情。
I'll probably go with the last solution. I just wanted to know if it's possible to do what I want using a left join.
推荐答案
这是一种通用的转换方法将查询从SQL服务器形式更新到PostgreSQL:
Here's a generic way to transform this update query from SQL-server form to 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 is a pseudo-column that points to the unique location of a row. You could use instead the primary key of the table if it had one.
该问题的查询#2不能满足您的期望,因为更新后的表 Users
永远不会加入FROM子句中的同一表 Users u
。就像您在FROM子句中两次放置一个表名一样,它们不会隐式地连接或绑定在一起,它们被视为两组独立的行。
The query #2 from the question doesn't do what you expect because the updated table Users
is never joined to the same table Users u
in the FROM clause. Just as when you put a table name twice in a FROM clause, they don't get implicitly joined or bound together, they are considered as two independant sets of rows.
这篇关于Postgres从左联接更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!