簡體   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