如何在 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)
我有 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)