繁体   English   中英

如何在postgres中将唯一行从一个表插入到另一个表?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM