递归查询postgresql
recursive query postgresql
我在使用 sql 进行递归查询时遇到问题。我想知道解决这个问题的最佳方法是什么。
我有以下型号
这里应用程序基本上是有版本的,安装在不同的环境中。
需要注意的是,每个版本都有一个以前的版本,因此可以应用类似于 hotfix 的模型。
要知道环境中的工单,需要搜索最新版本的环境并进行递归
我的目标是构建一个 table 如下:
门票 | arrival_date_to_enviroment | arrival_version_to_enviroment |环境
我想我必须进行递归查询,才能知道哪些票在哪个版本中。
为此,我认为第一步是了解版本包含的版本
我可以通过以下方式提出一些问题来解决这部分问题:
WITH RECURSIVE version_recursive AS (
select v.name, v.version_from, v.application from versions v
where v.name='21.1204.0'
UNION
select v.name, v.version_from, v.application from versions v
JOIN version_recursive s ON s.version_from = v.name AND s.application = v.application
)
SELECT *
FROM version_recursive;
下一步是在环境中找到最新的部署并使用票证加入。
但我的主要问题之一是我不知道如何使用 sql
完成 arrival_version_to_enviroment
非常感谢任何帮助和建议。我需要使用 sql 来完成此操作,无需编程逻辑
如果我理解你到达的意思,这样的事情可能会做到:
- 遍历版本(递归),但保留每个相关先前版本的基础版本。
- 加入各种需要的细节
我在结果中包含了比要求的更多的细节,并且可能建议了更多。例如,了解引入票证的初始环境很有用,但此部署的当前环境也是如此。我决定只包括引入的初始环境。添加更多细节很简单。
SQL:
WITH RECURSIVE versionx (base, name, version_from, application, lv) AS (
SELECT name, name, version_from, application, 1 FROM versions
UNION ALL
SELECT v0.base, v1.name, v1.version_from, v1.application, lv+1
FROM versions AS v1
JOIN versionx AS v0
ON v0.version_from = v1.name
AND lv < 20 -- Temporary guard against bad data. Remove when ready.
)
SELECT t.id AS ticket_id -- The ticket
, d.date AS arrival_date -- Initial date ticket was introduced.
, x.name AS arrival_version -- Initial version ticket was introduced.
, x.base AS version -- Current version.
, d0.date AS cur_date -- Date of deployment of current version.
, e.name AS env_name -- Initial deployment environment
FROM versionx AS x
JOIN tickets AS t
ON t.version = x.name
JOIN deployments AS d
ON d.version = x.name
JOIN environments AS e
ON e.id = d.environment_id
JOIN deployments AS d0
ON d0.version = x.base
;
结果,基于给定的测试数据:
+-----------+--------------+-----------------+---------+------------+----------+
| ticket_id | arrival_date | arrival_version | version | cur_date | env_name |
+-----------+--------------+-----------------+---------+------------+----------+
| 1 | 2021-12-07 | ver01 | ver01 | 2021-12-07 | env01 |
| 1 | 2021-12-07 | ver01 | ver02 | 2021-12-08 | env01 |
| 2 | 2021-12-08 | ver02 | ver02 | 2021-12-08 | env02 |
+-----------+--------------+-----------------+---------+------------+----------+
测试数据:
SELECT * FROM versions;
+-------+--------------+-------------+
| name | version_from | application |
+-------+--------------+-------------+
| ver01 | NULL | app01 |
| ver02 | ver01 | app02 |
+-------+--------------+-------------+
SELECT * FROM deployments;
+------+----------------+------------+---------+
| id | environment_id | date | version |
+------+----------------+------------+---------+
| 1 | 1 | 2021-12-07 | ver01 |
| 2 | 2 | 2021-12-08 | ver02 |
+------+----------------+------------+---------+
SELECT * FROM environments;
+------+-------+-------------+-------+
| id | name | application | url |
+------+-------+-------------+-------+
| 1 | env01 | app01 | url01 |
| 2 | env02 | app02 | url02 |
+------+-------+-------------+-------+
SELECT * FROM tickets;
+------+---------+
| id | version |
+------+---------+
| 1 | ver01 |
| 2 | ver02 |
+------+---------+
不同的例子:
-- creating table
CREATE TABLE versions (
"name" text NULL,
version_from text NULL,
aqpplication text NULL
);
-- insert sample data for test
INSERT INTO versions ("name", version_from, aqpplication) VALUES('1.0', NULL, 'app1');
INSERT INTO versions ("name", version_from, aqpplication) VALUES('1.1', '1.0', 'app1');
INSERT INTO versions ("name", version_from, aqpplication) VALUES('1.2', '1.1', 'app1');
INSERT INTO versions ("name", version_from, aqpplication) VALUES('1.3', '1.21', 'app1');
INSERT INTO versions ("name", version_from, aqpplication) VALUES('5.5', NULL, 'app2');
INSERT INTO versions ("name", version_from, aqpplication) VALUES('5.6', '5.5', 'app2');
INSERT INTO versions ("name", version_from, aqpplication) VALUES('5.7', '5.6', 'app2');
INSERT INTO versions ("name", version_from, aqpplication) VALUES('5.8', '5.7', 'app2');
INSERT INTO versions ("name", version_from, aqpplication) VALUES('1.4', '1.3', 'app1');
-- recursive select query
WITH RECURSIVE version_recursive(name, version_from, application, version_history) AS (
SELECT vn.*, vn."name"::text
FROM versions AS vn
WHERE vn.version_from is null
UNION ALL
SELECT v.*,
(v_rec.version_history || '->' || v."name"::TEXT)
FROM version_recursive as v_rec, versions AS v
WHERE v.version_from = v_rec."name"
)
SELECT * FROM version_recursive ORDER BY "name";
Result:
+--------+--------------+-------------+--------------------+
| name | version_from | application | version_history |
+--------+--------------+-------------+--------------------+
| 1.0 | NULL | app1 | 1.0 |
| 1.1 | 1.0 | app1 | 1.0->1.1 |
| 1.2 | 1.1 | app1 | 1.0->1.1->1.2 |
| 5.5 | NULL | app2 | 5.5 |
| 5.6 | 5.5 | app2 | 5.5->5.6 |
| 5.7 | 5.6 | app2 | 5.5->5.6->5.7 |
| 5.8 | 5.7 | app2 | 5.5->5.6->5.7->5.8 |
+--------+--------------+-------------+--------------------+
我在使用 sql 进行递归查询时遇到问题。我想知道解决这个问题的最佳方法是什么。
我有以下型号
这里应用程序基本上是有版本的,安装在不同的环境中。 需要注意的是,每个版本都有一个以前的版本,因此可以应用类似于 hotfix 的模型。 要知道环境中的工单,需要搜索最新版本的环境并进行递归
我的目标是构建一个 table 如下:
门票 | arrival_date_to_enviroment | arrival_version_to_enviroment |环境
我想我必须进行递归查询,才能知道哪些票在哪个版本中。 为此,我认为第一步是了解版本包含的版本 我可以通过以下方式提出一些问题来解决这部分问题:
WITH RECURSIVE version_recursive AS (
select v.name, v.version_from, v.application from versions v
where v.name='21.1204.0'
UNION
select v.name, v.version_from, v.application from versions v
JOIN version_recursive s ON s.version_from = v.name AND s.application = v.application
)
SELECT *
FROM version_recursive;
下一步是在环境中找到最新的部署并使用票证加入。
但我的主要问题之一是我不知道如何使用 sql
完成 arrival_version_to_enviroment非常感谢任何帮助和建议。我需要使用 sql 来完成此操作,无需编程逻辑
如果我理解你到达的意思,这样的事情可能会做到:
- 遍历版本(递归),但保留每个相关先前版本的基础版本。
- 加入各种需要的细节
我在结果中包含了比要求的更多的细节,并且可能建议了更多。例如,了解引入票证的初始环境很有用,但此部署的当前环境也是如此。我决定只包括引入的初始环境。添加更多细节很简单。
SQL:
WITH RECURSIVE versionx (base, name, version_from, application, lv) AS (
SELECT name, name, version_from, application, 1 FROM versions
UNION ALL
SELECT v0.base, v1.name, v1.version_from, v1.application, lv+1
FROM versions AS v1
JOIN versionx AS v0
ON v0.version_from = v1.name
AND lv < 20 -- Temporary guard against bad data. Remove when ready.
)
SELECT t.id AS ticket_id -- The ticket
, d.date AS arrival_date -- Initial date ticket was introduced.
, x.name AS arrival_version -- Initial version ticket was introduced.
, x.base AS version -- Current version.
, d0.date AS cur_date -- Date of deployment of current version.
, e.name AS env_name -- Initial deployment environment
FROM versionx AS x
JOIN tickets AS t
ON t.version = x.name
JOIN deployments AS d
ON d.version = x.name
JOIN environments AS e
ON e.id = d.environment_id
JOIN deployments AS d0
ON d0.version = x.base
;
结果,基于给定的测试数据:
+-----------+--------------+-----------------+---------+------------+----------+
| ticket_id | arrival_date | arrival_version | version | cur_date | env_name |
+-----------+--------------+-----------------+---------+------------+----------+
| 1 | 2021-12-07 | ver01 | ver01 | 2021-12-07 | env01 |
| 1 | 2021-12-07 | ver01 | ver02 | 2021-12-08 | env01 |
| 2 | 2021-12-08 | ver02 | ver02 | 2021-12-08 | env02 |
+-----------+--------------+-----------------+---------+------------+----------+
测试数据:
SELECT * FROM versions;
+-------+--------------+-------------+
| name | version_from | application |
+-------+--------------+-------------+
| ver01 | NULL | app01 |
| ver02 | ver01 | app02 |
+-------+--------------+-------------+
SELECT * FROM deployments;
+------+----------------+------------+---------+
| id | environment_id | date | version |
+------+----------------+------------+---------+
| 1 | 1 | 2021-12-07 | ver01 |
| 2 | 2 | 2021-12-08 | ver02 |
+------+----------------+------------+---------+
SELECT * FROM environments;
+------+-------+-------------+-------+
| id | name | application | url |
+------+-------+-------------+-------+
| 1 | env01 | app01 | url01 |
| 2 | env02 | app02 | url02 |
+------+-------+-------------+-------+
SELECT * FROM tickets;
+------+---------+
| id | version |
+------+---------+
| 1 | ver01 |
| 2 | ver02 |
+------+---------+
不同的例子:
-- creating table
CREATE TABLE versions (
"name" text NULL,
version_from text NULL,
aqpplication text NULL
);
-- insert sample data for test
INSERT INTO versions ("name", version_from, aqpplication) VALUES('1.0', NULL, 'app1');
INSERT INTO versions ("name", version_from, aqpplication) VALUES('1.1', '1.0', 'app1');
INSERT INTO versions ("name", version_from, aqpplication) VALUES('1.2', '1.1', 'app1');
INSERT INTO versions ("name", version_from, aqpplication) VALUES('1.3', '1.21', 'app1');
INSERT INTO versions ("name", version_from, aqpplication) VALUES('5.5', NULL, 'app2');
INSERT INTO versions ("name", version_from, aqpplication) VALUES('5.6', '5.5', 'app2');
INSERT INTO versions ("name", version_from, aqpplication) VALUES('5.7', '5.6', 'app2');
INSERT INTO versions ("name", version_from, aqpplication) VALUES('5.8', '5.7', 'app2');
INSERT INTO versions ("name", version_from, aqpplication) VALUES('1.4', '1.3', 'app1');
-- recursive select query
WITH RECURSIVE version_recursive(name, version_from, application, version_history) AS (
SELECT vn.*, vn."name"::text
FROM versions AS vn
WHERE vn.version_from is null
UNION ALL
SELECT v.*,
(v_rec.version_history || '->' || v."name"::TEXT)
FROM version_recursive as v_rec, versions AS v
WHERE v.version_from = v_rec."name"
)
SELECT * FROM version_recursive ORDER BY "name";
Result:
+--------+--------------+-------------+--------------------+
| name | version_from | application | version_history |
+--------+--------------+-------------+--------------------+
| 1.0 | NULL | app1 | 1.0 |
| 1.1 | 1.0 | app1 | 1.0->1.1 |
| 1.2 | 1.1 | app1 | 1.0->1.1->1.2 |
| 5.5 | NULL | app2 | 5.5 |
| 5.6 | 5.5 | app2 | 5.5->5.6 |
| 5.7 | 5.6 | app2 | 5.5->5.6->5.7 |
| 5.8 | 5.7 | app2 | 5.5->5.6->5.7->5.8 |
+--------+--------------+-------------+--------------------+