PSQL查询根据条件将记录从一个表插入到另一个表

时间:2020-10-30 10:42:10

标签: sql postgresql subquery case sql-insert

我有2个具有以下结构的Postgres表:


                              Table "public.tmp"
      Column       |          Type           | Collation | Nullable | Default 
-------------------+-------------------------+-----------+----------+---------
 MY_SL             | character varying(50)   |           |          | 
 Release           | character varying(50)   |           |          | 
 HOST              | character varying(50)   |           | not null | 
 UN NO.            | character varying(50)   |           |          | 
 STATUS            | character varying(50)   |           |          | 
 S_DATE            | character varying(50)   |           | not null | 

                                        Table "public.mo"
      Column       |          Type           | Collation | Nullable |                 Default                 
-------------------+-------------------------+-----------+----------+-----------------------------------------
 id                | integer                 |           | not null | nextval('mbss_output_id_seq'::regclass)
 HOST              | character varying(50)   |           | not null | 
 UN NO.            | character varying(50)   |           |          | 
 STATUS            | character varying(50)   |           |          | 
 S_DATE            | character varying(50)   |           | not null | 
 compliant_status  | character varying(50)   |           | not null |

让我们说我在tmp表中有如下数据:

Table: tmp

 MY_SL | Release | HOST       |  UN NO.|  STATUS   |      S_DATE    
------------+-------------+-----------+----------------------+------------------
 2     | 1       | RhelTest   | 7:1:8  | COMPLIANT | 2020-08-26T15:16:48Z 
 12    | 1       | RhelTest   | 7:1:9  | COMPLIANT | 2020-08-26T15:16:48Z 
 22    | 2       | RhelTest   | 7:2:1  | COMPLIANT | 2020-08-26T15:16:48Z 
 4     | 1       | RhelTest   | 7:2:10 | NC        | 2020-08-26T15:16:48Z 
 11    | 2       | RhelTest   | 7:2:11 | NC        | 2020-08-26T15:16:48Z 
 1     | 3       | Demo1      | 7:2:11 | NC        | 2020-08-26T15:16:48Z 
 23    | 3       | Demo1      | 7:2:11 | NC        | 2020-08-26T15:16:48Z 
 333   | 3       | Demo2      | 7:2:11 | COMPLIANT | 2020-08-26T15:16:48Z 

现在,我想编写一个psql INSERT INTO查询,该查询会将数据从public.tmp复制到public.mo表,并在以下条件下执行

当主机在“状态”列中具有混合值时,例如 主持人:RhelTest

  • “状态”列中有2个值分别为“ COMPLIANT”和“ NC”,则此类行的Compliance_status列应具有值“ PARTIAL”
  • 或者如果只有一个像'COMPLIANT'这样的值,则此类行的Compliance_status列应具有'COMPLIANT'值
  • 或者如果只有一个值(例如“ NC”),则此类行的Compliance_status列的值应为“ NON_COMPLIANT”

public.mo表中的最终预期输出:

Table: public.mo

 id | HOST       |  UN NO.|  STATUS   |      S_DATE          | compliant_status 
------------+-------------+-----------+----------------------+------------------
 1  | RhelTest   | 7:1:8  | COMPLIANT | 2020-08-26T15:16:48Z | PARTIAL
 2  | RhelTest   | 7:1:9  | COMPLIANT | 2020-08-26T15:16:48Z | PARTIAL
 3  | RhelTest   | 7:2:1  | COMPLIANT | 2020-08-26T15:16:48Z | PARTIAL
 4  | RhelTest   | 7:2:10 | NC        | 2020-08-26T15:16:48Z | PARTIAL
 5  | RhelTest   | 7:2:11 | NC        | 2020-08-26T15:16:48Z | PARTIAL
 6  | Demo1      | 7:2:11 | NC        | 2020-08-26T15:16:48Z | NON_COMPLIANT
 7  | Demo1      | 7:2:11 | NC        | 2020-08-26T15:16:48Z | NON_COMPLIANT
 8  | Demo2      | 7:2:11 | COMPLIANT | 2020-08-26T15:16:48Z | COMPLIANT

1 个答案:

答案 0 :(得分:0)

您可以使用窗口函数和case表达式。假设数据中显示的status只有两个可能的值,这是一种实现方法:

insert in mo (host, un_no, status, s_date, compliant_status)
select host, un_no, status, s_date,
    case 
        when min_host_status <> max_host_status then 'PARTIAL'
        when min_host_status = 'NC' then 'NON_COMPLIANT'
        else min_host_status
    end
from (
    select t.*,
        min(status) over(partition by host) min_host_status,
        max(status) over(partition by host) max_host_status
    from tmp t
) t

这个想法是比较每个status的{​​{1}}的最小值和最大值。如果存在差异,则host为“ PARTIAL”。否则,我们将“ NC”更改为“ NON_COMPLIANT”,并保留其他值(“ COMPLIANT”)。

在这里,子查询不是严格必需的,我们可以很好地在外部查询中直接使用window函数;我之所以使用它,是因为它避免了一次又一次地重复相同的表达式。