[英]How to insert unique rows from one table to another table in postgres?
我想将 product_table 中唯一的行插入到 bill_table_unique 中。
然后必须将重复的行从 product_table 移动到 bill_table_duplicate。
一旦所有的数据都被移动意味着 product_table 条目必须被清除(只有移动的行必须被清除)
输入:
产品表
id bill_id entry_date product_name stock
-------------------------------------------------------------------
1 009 2020-12-11 02:05:20.09876 apple 5
2 009 2020-12-11 02:05:20.09876 apple 5
3 009 2020-09-11 02:05:20.09876 apple 5
4 002 2020-12-11 02:05:20.09876 berry 5
5 002 2020-12-11 02:05:20.09876 berry 5
6 004 2020-12-11 10:05:20.09876 pineapple 1
7 006 2020-12-11 10:05:20.09876 pineapple 4
第 1步:将 product_table 中唯一的行插入到 bill_table_unique。
Output:bill_table_unique
id bill_id entry_date product_name stock
-------------------------------------------------------------------
1 009 2020-12-11 02:05:20.09876 apple 5
2 009 2020-09-11 02:05:20.09876 apple 5
3 002 2020-12-11 02:05:20.09876 berry 5
4 004 2020-12-11 10:05:20.09876 pineapple 1
5 006 2020-12-11 10:05:20.09876 pineapple 4
第 2步:然后必须将重复的行从 product_table 移动到 bill_table_duplicate。
Output:bill_table_duplicate
id bill_id entry_date product_name stock
---------------------------------------------------------------------
1 009 2020-12-11 02:05:20.09876 apple 5
2 002 2020-12-11 02:05:20.09876 berry 5
第 3 步:一旦所有数据都被移动意味着 product_table 条目必须被清除(只有移动的行必须被清除)
Output:product_table
id bill_id entry_date product_name stock
--------------------------------------------------------------------
使用如下两个查询:
Insert into bill_table_unique
Select distinct bill_id, entry_date, product_name, stock
From product_table;
Insert into bill_table_duplicate
Select bill_id, entry_date, product_name, stock
From
(Select bill_id, entry_date, product_name, stock,
Row_number() over (partirion by bill_id, entry_date, product_name, stock
order by null) as rn
From product_table) t
Where rn >= 2;
CREATE TABLE foo (id INTEGER PRIMARY KEY, bill_id TEXT NOT NULL,
entry_date TIMESTAMP NOT NULL, product_name TEXT NOT NULL,
stock INTEGER NOT NULL);
\copy foo from stdin
1 009 2020-12-11 02:05:20.09876 apple 5
2 009 2020-12-11 02:05:20.09876 apple 5
3 009 2020-09-11 02:05:20.09876 apple 5
4 002 2020-12-11 02:05:20.09876 berry 5
5 002 2020-12-11 02:05:20.09876 berry 5
6 004 2020-12-11 10:05:20.09876 pineapple 1
7 006 2020-12-11 10:05:20.09876 pineapple 4
\.
CREATE TABLE foo1 (id SERIAL PRIMARY KEY, bill_id TEXT NOT NULL,
entry_date TIMESTAMP NOT NULL, product_name TEXT NOT NULL,
stock INTEGER NOT NULL);
CREATE TABLE foo2 (id SERIAL PRIMARY KEY, bill_id TEXT NOT NULL,
entry_date TIMESTAMP NOT NULL, product_name TEXT NOT NULL,
stock INTEGER NOT NULL);
WITH a AS (
SELECT min(id) id, bill_id, entry_date, product_name, stock
FROM foo GROUP BY bill_id, entry_date, product_name, stock
), b AS (
INSERT INTO foo1 (bill_id, entry_date, product_name, stock)
SELECT bill_id, entry_date, product_name, stock FROM a)
INSERT INTO foo2 (bill_id, entry_date, product_name, stock)
SELECT f.bill_id, f.entry_date, f.product_name, f.stock
FROM foo f LEFT JOIN a USING (id) WHERE a.id IS NULL;
WITH 查询中的第一个 CTE 计算要传输到表 foo1 中的行。 我选择了具有最小 id 的行。
第二个 CTE 插入行。
第三个 CTE 插入上一步中没有插入的行,这些是重复的。
如果行数不太大,这应该使用 hashaggregate 和 hashjoin,并且比使用排序的查询快得多。 此外,重复数据删除只进行一次。
第 3 步:一旦所有数据都已被移动意味着 product_table 条目必须被清除(只有移动的行必须被清除)
由于问题没有指定不应该移动哪些行的条件,因此原始表中的所有行都已移动,因此:
TRUNCATE TABLE product_table;
我会使用row_number()
来枚举原始表中的行。 然后插入其他表只依赖简单的过滤器:
WITH pt AS (
SELECT pt.*,
ROW_NUMBER() OVER (PARTITION BY bill_id, entry_date, product_name, stock ORDER BY id) as seqnum
FROM product_table pt
),
btu AS (
INSERT INTO bill_table_unique (bill_id, entry_date, product_name, stock)
SELECT bill_id, entry_date, product_name, stock
FROM pt
WHERE seqnum = 1
)
INSERT INTO bill_table_duplicate (bill_id, entry_date, product_name, stock)
SELECT bill_id, entry_date, product_name, stock
FROM pt
WHERE seqnum > 1;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.