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 a
和 c
,单独保留 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
列相关,该列在示例数据中可以为空。
如何删除 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 a
和 c
,单独保留 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
列相关,该列在示例数据中可以为空。