使用 PostgresSQL 的递归 SQL 查询
Recursive SQL Queries with PostgreSQL
场景:
我有一个应用程序可以接收一个或多个输入并生成一个或多个输出。
应用程序可以使用一次或多次执行的输出作为新执行的输入。
在某些情况下,数据会失效,并且所有直接或间接使用该数据的执行生成的输出数据也必须失效。
这就是我尝试完成它的方式:
CREATE TABLE execution (
execution_id INT,
data VARCHAR(36),
direction CHAR(1) NOT NULL CHECK (direction = 'I' OR direction = 'O'),
PRIMARY KEY (execution_id, data));
INSERT INTO execution VALUES (1, 'aaaa', 'O');
INSERT INTO execution VALUES (1, 'bbbb', 'O');
INSERT INTO execution VALUES (2, 'aaaa', 'I');
INSERT INTO execution VALUES (2, 'bbbb', 'I');
INSERT INTO execution VALUES (2, 'cccc', 'O');
INSERT INTO execution VALUES (2, 'dddd', 'O');
INSERT INTO execution VALUES (3, 'aaaa', 'I');
INSERT INTO execution VALUES (3, 'cccc', 'I');
INSERT INTO execution VALUES (3, 'eeee', 'O');
INSERT INTO execution VALUES (4, 'bbbb', 'I');
INSERT INTO execution VALUES (4, 'ffff', 'O');
对于此数据,当我请求将受到 'aaaa' 数据失效影响的执行链时,我希望得到:
- INSERT INTO execution VALUES (2, 'cccc', 'O');
- INSERT INTO execution VALUES (2, 'dddd', 'O');
- INSERT INTO execution VALUES (3, 'eeee', 'O');
原因:
- 执行 2 使用 'aaaa' 作为输入,因此 'cccc' 和 'dddd' 也应该无效。
- 执行 3 也使用 'aaaa' 作为输入和 'cccc'(这只是无效),所以 'eeee' 也应该无效。
- 等等...
查询:
WITH RECURSIVE execution_chain AS (
SELECT execution_id, data, direction, 1 AS level
FROM execution
WHERE data = 'aaaa' AND direction = 'O'
UNION ALL
SELECT e.execution_id, e.data, e.direction, e.level + 1
FROM execution e
WHERE e.execution_id IN (
SELECT e.execution_id
FROM execution e
JOIN execution_chain
ON e.data = execution_chain.data
WHERE e.execution_id > execution_chain.execution_id
)
AND e.direction = 'O'
)
SELECT * FROM execution_chain;
我收到这个错误:
ERROR: recursive reference to query "execution_chain" must not appear within a subquery
LINE 11: JOIN execution_chain ec
^
SQL state: 42P19
Character: 339
任何关于如何“修复”此查询的想法都将不胜感激。
为了简化查询,首先计算要遵循的执行依赖关系
WITH RECURSIVE dep as (
select i.data, i.execution_id idin, o.execution_id idout
from execution i
join execution o on i.data = o.data and i.direction = 'I' and o.direction = 'O'
),
execution_chain AS (
SELECT execution_id, data, direction, 1 AS level
FROM execution
WHERE data = 'aaaa' and direction = 'O'
UNION ALL
SELECT e.execution_id, e.data, e.direction, ec.level + 1
FROM execution_chain ec
JOIN dep ON dep.data = ec.data AND dep.idout = ec.execution_id
JOIN execution e ON e.execution_id = dep.idin AND e.direction ='O'
)
SELECT distinct execution_id, data, direction
FROM execution_chain
WHERE level > 1
ORDER BY execution_id, data;
场景:
我有一个应用程序可以接收一个或多个输入并生成一个或多个输出。
应用程序可以使用一次或多次执行的输出作为新执行的输入。
在某些情况下,数据会失效,并且所有直接或间接使用该数据的执行生成的输出数据也必须失效。
这就是我尝试完成它的方式:
CREATE TABLE execution (
execution_id INT,
data VARCHAR(36),
direction CHAR(1) NOT NULL CHECK (direction = 'I' OR direction = 'O'),
PRIMARY KEY (execution_id, data));
INSERT INTO execution VALUES (1, 'aaaa', 'O');
INSERT INTO execution VALUES (1, 'bbbb', 'O');
INSERT INTO execution VALUES (2, 'aaaa', 'I');
INSERT INTO execution VALUES (2, 'bbbb', 'I');
INSERT INTO execution VALUES (2, 'cccc', 'O');
INSERT INTO execution VALUES (2, 'dddd', 'O');
INSERT INTO execution VALUES (3, 'aaaa', 'I');
INSERT INTO execution VALUES (3, 'cccc', 'I');
INSERT INTO execution VALUES (3, 'eeee', 'O');
INSERT INTO execution VALUES (4, 'bbbb', 'I');
INSERT INTO execution VALUES (4, 'ffff', 'O');
对于此数据,当我请求将受到 'aaaa' 数据失效影响的执行链时,我希望得到:
- INSERT INTO execution VALUES (2, 'cccc', 'O');
- INSERT INTO execution VALUES (2, 'dddd', 'O');
- INSERT INTO execution VALUES (3, 'eeee', 'O');
原因:
- 执行 2 使用 'aaaa' 作为输入,因此 'cccc' 和 'dddd' 也应该无效。
- 执行 3 也使用 'aaaa' 作为输入和 'cccc'(这只是无效),所以 'eeee' 也应该无效。
- 等等...
查询:
WITH RECURSIVE execution_chain AS (
SELECT execution_id, data, direction, 1 AS level
FROM execution
WHERE data = 'aaaa' AND direction = 'O'
UNION ALL
SELECT e.execution_id, e.data, e.direction, e.level + 1
FROM execution e
WHERE e.execution_id IN (
SELECT e.execution_id
FROM execution e
JOIN execution_chain
ON e.data = execution_chain.data
WHERE e.execution_id > execution_chain.execution_id
)
AND e.direction = 'O'
)
SELECT * FROM execution_chain;
我收到这个错误:
ERROR: recursive reference to query "execution_chain" must not appear within a subquery
LINE 11: JOIN execution_chain ec
^
SQL state: 42P19
Character: 339
任何关于如何“修复”此查询的想法都将不胜感激。
为了简化查询,首先计算要遵循的执行依赖关系
WITH RECURSIVE dep as (
select i.data, i.execution_id idin, o.execution_id idout
from execution i
join execution o on i.data = o.data and i.direction = 'I' and o.direction = 'O'
),
execution_chain AS (
SELECT execution_id, data, direction, 1 AS level
FROM execution
WHERE data = 'aaaa' and direction = 'O'
UNION ALL
SELECT e.execution_id, e.data, e.direction, ec.level + 1
FROM execution_chain ec
JOIN dep ON dep.data = ec.data AND dep.idout = ec.execution_id
JOIN execution e ON e.execution_id = dep.idin AND e.direction ='O'
)
SELECT distinct execution_id, data, direction
FROM execution_chain
WHERE level > 1
ORDER BY execution_id, data;