如何在 postgres 中用另一个 table 中的行来完成 table 中缺失的行?

How to complete missing rows from a table with rows from another table in postgres?

我有 2 个操作 table,一个是特定的,一个是一般的,基于状态和相关操作。 在第一个 table 中,缺少一些行(基于状态)。 我正在尝试 return 一个全局 table ,只要第一行中缺少一行,它就会从第二个 table (default_action) 中选择丢失的行。

工作table:job_actions
默认table:default_actions

我正在使用以下设置进行测试:

CREATE TYPE STATUS AS ENUM('In Progress', 'Failed', 'Completed');

CREATE TYPE EXPIRATION_ACTION AS ENUM('Expire', 'Delete');

CREATE TYPE BASIC_ACTION AS (status STATUS,
    operation EXPIRATION_ACTION, expiration_time TIMESTAMP);
   
  
CREATE TYPE ACTION AS (partition VARCHAR(40), job VARCHAR(48), b_action BASIC_ACTION);


CREATE TABLE IF NOT EXISTS job_actions (
  partition VARCHAR(40),
  job VARCHAR(48),
  status STATUS,
  operation EXPIRATION_ACTION,
  expiration_time TIMESTAMP
  );

CREATE TABLE IF NOT EXISTS default_actions OF BASIC_ACTION;
INSERT INTO default_actions (
       status,
       operation,
       expiration_time
       )
VALUES ('In Progress', 'Expire', 'infinity'::timestamp),
      ('Failed', 'Expire', 'infinity'::timestamp),
      ('Completed', 'Expire', 'infinity'::timestamp);

INSERT INTO job_actions (
   partition ,
   job ,
   status,
   operation,
   expiration_time
    )   
  VALUES 
     ('part1', 'job1','Failed', 'Expire', NOW() + INTERVAL '1 hour'),
     ('part1', 'job2','In Progress', 'Expire', NOW() + INTERVAL '1     hour'),
     ('part1', 'job2','Failed', 'Expire', NOW() + INTERVAL '1 hour'),
     ('part1', 'job3','In Progress', 'Expire', NOW() + INTERVAL '1 hour'),
     ('part1', 'job3','Failed', 'Expire', NOW() + INTERVAL '1 hour');  

我正在尝试使用类似

的东西
SELECT ja.partition, ja.job, ja.status, ja.operation, ja.expiration_time
FROM job_actions ja 
WHERE NOT EXISTS (
SELECT da.status, da.operation, da.expiration_time
FROM default_actions da );

但目前,它 return 是空的 table。 这是预期的结果:


有人知道我做错了什么吗?

首先,从 job_actions 获取所有分区和作业。然后用 default_actions 交叉连接以获得所有可能的组合。将其与 job_actions 左连接并从那里获取 expiration_time 除非它是 NULL 值(未找到匹配的行)。

翻译成SQL:

SELECT partition, job, status, operation,
       coalesce(ja.expiration_time, da.expiration_time) AS expiration_time
FROM (SELECT DISTINCT partition, job
      FROM job_actions) AS jobs
   CROSS JOIN default_actions AS da
   LEFT JOIN job_actions AS ja USING (partition, job, status, operation)

ORDER BY partition, job, status;
 partition │ job  │   status    │ operation │      expiration_time       
═══════════╪══════╪═════════════╪═══════════╪════════════════════════════
 part1     │ job1 │ In Progress │ Expire    │ infinity
 part1     │ job1 │ Failed      │ Expire    │ 2021-06-18 14:57:23.912874
 part1     │ job1 │ Completed   │ Expire    │ infinity
 part1     │ job2 │ In Progress │ Expire    │ 2021-06-18 14:57:23.912874
 part1     │ job2 │ Failed      │ Expire    │ 2021-06-18 14:57:23.912874
 part1     │ job2 │ Completed   │ Expire    │ infinity
 part1     │ job3 │ In Progress │ Expire    │ 2021-06-18 14:57:23.912874
 part1     │ job3 │ Failed      │ Expire    │ 2021-06-18 14:57:23.912874
 part1     │ job3 │ Completed   │ Expire    │ infinity
(9 rows)