【问题标题】:How to insert unique rows from one table to another table in postgres?如何在postgres中将唯一行从一个表插入到另一个表?
【发布时间】:2021-04-25 16:07:39
【问题描述】:

我想将 product_table 中唯一的行插入 bill_table_unique。

然后必须将重复的行从 product_table 移动到 bill_table_duplicate。

一旦所有的数据都被移动了意味着 product_table 条目必须被清除(只有移动的行需要被清除)

输入

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。

输出: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。

输出: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 条目必须被清除(只需要清除移动的行)

输出:product_table

id     bill_id     entry_date                   product_name stock
--------------------------------------------------------------------

【问题讨论】:

    标签: sql postgresql duplicates unique distinct


    【解决方案1】:

    使用如下两个查询:

    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;
    

    【讨论】:

      【解决方案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;
      

      【讨论】:

        【解决方案3】:

        我会使用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;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-10-11
          • 1970-01-01
          • 1970-01-01
          • 2022-01-19
          • 2014-07-29
          • 1970-01-01
          相关资源
          最近更新 更多