递归查询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 来完成此操作,无需编程逻辑

如果我理解你到达的意思,这样的事情可能会做到:

  1. 遍历版本(递归),但保留每个相关先前版本的基础版本。
  2. 加入各种需要的细节

我在结果中包含了比要求的更多的细节,并且可能建议了更多。例如,了解引入票证的初始环境很有用,但此部署的当前环境也是如此。我决定只包括引入的初始环境。添加更多细节很简单。

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 |
+--------+--------------+-------------+--------------------+