PostgreSQL 10:如何仅在 Table B 中存在的 ID 上删除 Table A 中的孤立行?

PostgreSQL 10: How to delete orphan rows in Table A on only IDs existing in Table B?

如何删除 Table A 中的孤立行 * 表示孤立行:

+---------+--------+----------+-------+
| ID      | option | category | rates | Table A
+---------+--------+----------+-------+
| a       | f      | null     | 2.5   |
+---------+--------+----------+-------+
| a       | f      | d        | 2     |*
+---------+--------+----------+-------+
| a       | g      | e        | 3     |
+---------+--------+----------+-------+
| c       | g      | e        | 4     |
+---------+--------+----------+-------+
| d       | f      | d        | 1     |
+---------+--------+----------+-------+

仅在 Table B 中存在的 ID(仅检查 ID ac,单独保留 d):

+---------+--------+----------+-------+
| ID      | option | category | rates | Table B
+---------+--------+----------+-------+
| a       | f      | null     | 2.5   |
+---------+--------+----------+-------+
| a       | g      | e        | 3     |
+---------+--------+----------+-------+
| c       | g      | e        | 4     |
+---------+--------+----------+-------+

结果(只删除了第二行a,f,d,2):

+---------+--------+----------+-------+
| ID      | option | category | rates | Table A
+---------+--------+----------+-------+
| a       | f      | null     | 2.5   |
+---------+--------+----------+-------+
| a       | g      | e        | 3     |
+---------+--------+----------+-------+
| c       | g      | e        | 4     |
+---------+--------+----------+-------+
| d       | f      | d        | 1     |
+---------+--------+----------+-------+

这只是一个示例,真实的 table 包含更多 ID 和变体。

我的想法是,我应该 Table B 上的 group by ID 临时 table 然后 loop 删除每个 ID Table A 上的非匹配行。

因为我是 PostgreSQL 的新手,你能告诉我如何做到这一点吗?我搜索了循环删除,但不确定如何将 ID 从 temp table 传递到循环。另外,如果有更好的方法,也请告诉我。提前致谢!

delete from A using (
select distinct A.* from A, B where A.ID = B.ID   --- all A that have same ID with B
except 
select * from B 
) x   ---- this one has all A rows without B rows only where A.id = B.id
where --- now the join
   A.ID = x.ID and
   A.option = x.option and
   A.category = X.category and
   A.rates = X.rates

最好PK清楚,ID容易误导,通常一个ID是唯一的

你似乎想要这个:

DELETE from tableA
 USING tableB
 WHERE 
   -- ignore rows with IDs that don't exist in tableB
   tableA.ID = tableB.ID
   -- ignore rows that have an exact all-column match in tableB
   AND NOT EXISTS (select * from tableB where tableB.* is not distinct from tableA.*);

is not distinct from 有点像 "equals"(= 运算符),不同之处在于当比较的列均为 NULL 时也是如此,而 row(x,null) = row(x,null) 为空,而不是真的。这至少与您的 category 列相关,该列在示例数据中可以为空。