用于更新列的递归 PostgreSQL 查询
Recursive PostgreSQL Query for Updating Column
您好,我正在尝试使用 SQL 查询递归更新数据库列。
我有 2 tables module
和 module_dependency
.
第一个 table module
有列(带有示例数据):
id, name, state,
1, "website", "installed"
2, "purchase", "installed"
3, "crm", "installed"
4, "sale", "uninstalled"
5, "account", "installed"
6, "website_sale", "installed"
7, "purchase_bonus", "installed"
8, "website_blog", "installed"
9, "sale_discount", "installed"
10, "website_online", "installed"
第二个 table module_dependency
有列(带有示例数据):
id | dependency_name | module_id
----+-----------------+-----------
1 | website_sale | 1
2 | sale_bonus | 4
3 | website_blog | 1
4 | sale_discount | 4
5 | website_online | 1
6 | crm | 10
7 | account | 3
我需要将网站模块的状态更改为“升级”及其所有相关模块。
我可以检查当前模块的状态:
SELECT * FROM module WHERE name = 'website' AND state = 'installed';
id | name | state
----+---------+-----------
1 | website | installed
要获取网站模块的所有依赖项,我使用查询:
SELECT m.name, md.dependency_name , md.module_id
FROM module m JOIN module_dependency md ON (m.id = md.module_id)
WHERE m.name = 'website' AND m.state = 'installed';
name | dependency_name | module_id
---------+-----------------+-----------
website | website_sale | 1
website | website_blog | 1
website | website_online | 1
表示website_sale、website_blog、website_online 取决于 module_id 1 即网站。
主要问题是 website_online 依赖于 crm 和 crm on account 模块。
SELECT m.name, md.dependency_name , md.module_id
FROM module m JOIN module_dependency md ON (m.id = md.module_id)
WHERE m.name = 'website_online' AND m.state = 'installed';
name | dependency_name | module_id
----------------+-----------------+-----------
website_online | crm | 10
SELECT m.name, md.dependency_name , md.module_id
FROM module m JOIN module_dependency md ON (m.id = md.module_id)
WHERE m.name = 'crm' AND m.state = 'installed';
name | dependency_name | module_id
------+-----------------+-----------
crm | account | 3
我需要递归地将所有网站依赖项的状态更改为“升级”。更新后的行应如下所示:
id, name, state,
1, "website", "to upgrade"
3, "crm", "to upgrade"
5, "account", "to upgrade"
6, "website_sale", "to upgrade"
8, "website_blog", "to upgrade"
10, "website_online", "to upgrade"
您可以使用测试数据创建 tables:
CREATE TABLE module(id integer, name text, state text);
INSERT INTO module VALUES
(1, 'website', 'installed'),
(2, 'purchase', 'installed'),
(3, 'crm', 'installed'),
(4, 'sale', 'uninstalled'),
(5, 'account', 'installed'),
(6, 'website_sale', 'installed'),
(7, 'purchase_bonus', 'installed'),
(8, 'website_blog', 'installed'),
(9, 'sale_discount', 'installed'),
(10, 'website_online', 'installed');
CREATE TABLE module_dependency(id integer, dependency_name text, module_id integer);
INSERT INTO module_dependency VALUES
(1, 'website_sale', 1),
(2, 'sale_bonus', 4),
(3, 'website_blog', 1),
(4, 'sale_discount', 4),
(5, 'website_online', 1),
(6, 'crm', 10),
(7, 'account', 3);
我尝试编写递归查询,但没有成功。看起来像无限循环。如果我可以获得模块 table 的所有模块 ID,我可以简单地更新选定的条目。
WITH RECURSIVE modules_to_upgrade AS
(
SELECT id
FROM module
WHERE name = 'website'
UNION ALL
SELECT md.module_id
FROM module_dependency md JOIN modules_to_upgrade mtu on mtu.id = md.module_id
)
select * from modules_to_upgrade;
为了 link 递归部分回到模块,你似乎不能使用依赖 ID。
所以它必须在名字上。
WITH RECURSIVE rcte_modules_to_upgrade AS
(
SELECT
m.id as module_id
, m.name as module_name
, md.id as dependency_id
, md.dependency_name
, m.id as base_module_id
, 1 as depth
FROM module m
JOIN module_dependency md
ON md.module_id = m.id
WHERE m.name = 'website'
UNION ALL
SELECT
m.id
, m.name
, md.id
, md.dependency_name
, rcte.base_module_id
, rcte.depth + 1
FROM rcte_modules_to_upgrade rcte
JOIN module m
ON m.name = rcte.dependency_name
LEFT JOIN module_dependency md
ON md.module_id = m.id
)
select *
from rcte_modules_to_upgrade;
module_id | module_name | dependency_id | dependency_name | base_module_id | depth
--------: | :------------- | ------------: | :-------------- | -------------: | ----:
1 | website | 1 | website_sale | 1 | 1
1 | website | 3 | website_blog | 1 | 1
1 | website | 5 | website_online | 1 | 1
6 | website_sale | null | null | 1 | 2
8 | website_blog | null | null | 1 | 2
10 | website_online | 6 | crm | 1 | 2
3 | crm | 7 | account | 1 | 3
5 | account | null | null | 1 | 4
WITH RECURSIVE rcte_modules_to_upgrade AS
(
SELECT
m.id as module_id
, md.dependency_name
FROM module m
JOIN module_dependency md
ON md.module_id = m.id
WHERE m.name = 'website'
UNION ALL
SELECT
m.id
, md.dependency_name
FROM rcte_modules_to_upgrade rcte
JOIN module m
ON m.name = rcte.dependency_name
LEFT JOIN module_dependency md
ON md.module_id = m.id
)
update module
set state = 'to upgrade'
where id in (select distinct module_id
from rcte_modules_to_upgrade);
6 rows affected
select * from module order by id;
id | name | state
-: | :------------- | :----------
1 | website | to upgrade
2 | purchase | installed
3 | crm | to upgrade
4 | sale | uninstalled
5 | account | to upgrade
6 | website_sale | to upgrade
7 | purchase_bonus | installed
8 | website_blog | to upgrade
9 | sale_discount | installed
10 | website_online | to upgrade
db<>fiddle here
您好,我正在尝试使用 SQL 查询递归更新数据库列。
我有 2 tables module
和 module_dependency
.
第一个 table module
有列(带有示例数据):
id, name, state,
1, "website", "installed"
2, "purchase", "installed"
3, "crm", "installed"
4, "sale", "uninstalled"
5, "account", "installed"
6, "website_sale", "installed"
7, "purchase_bonus", "installed"
8, "website_blog", "installed"
9, "sale_discount", "installed"
10, "website_online", "installed"
第二个 table module_dependency
有列(带有示例数据):
id | dependency_name | module_id
----+-----------------+-----------
1 | website_sale | 1
2 | sale_bonus | 4
3 | website_blog | 1
4 | sale_discount | 4
5 | website_online | 1
6 | crm | 10
7 | account | 3
我需要将网站模块的状态更改为“升级”及其所有相关模块。
我可以检查当前模块的状态:
SELECT * FROM module WHERE name = 'website' AND state = 'installed';
id | name | state
----+---------+-----------
1 | website | installed
要获取网站模块的所有依赖项,我使用查询:
SELECT m.name, md.dependency_name , md.module_id
FROM module m JOIN module_dependency md ON (m.id = md.module_id)
WHERE m.name = 'website' AND m.state = 'installed';
name | dependency_name | module_id
---------+-----------------+-----------
website | website_sale | 1
website | website_blog | 1
website | website_online | 1
表示website_sale、website_blog、website_online 取决于 module_id 1 即网站。
主要问题是 website_online 依赖于 crm 和 crm on account 模块。
SELECT m.name, md.dependency_name , md.module_id
FROM module m JOIN module_dependency md ON (m.id = md.module_id)
WHERE m.name = 'website_online' AND m.state = 'installed';
name | dependency_name | module_id
----------------+-----------------+-----------
website_online | crm | 10
SELECT m.name, md.dependency_name , md.module_id
FROM module m JOIN module_dependency md ON (m.id = md.module_id)
WHERE m.name = 'crm' AND m.state = 'installed';
name | dependency_name | module_id
------+-----------------+-----------
crm | account | 3
我需要递归地将所有网站依赖项的状态更改为“升级”。更新后的行应如下所示:
id, name, state,
1, "website", "to upgrade"
3, "crm", "to upgrade"
5, "account", "to upgrade"
6, "website_sale", "to upgrade"
8, "website_blog", "to upgrade"
10, "website_online", "to upgrade"
您可以使用测试数据创建 tables:
CREATE TABLE module(id integer, name text, state text);
INSERT INTO module VALUES
(1, 'website', 'installed'),
(2, 'purchase', 'installed'),
(3, 'crm', 'installed'),
(4, 'sale', 'uninstalled'),
(5, 'account', 'installed'),
(6, 'website_sale', 'installed'),
(7, 'purchase_bonus', 'installed'),
(8, 'website_blog', 'installed'),
(9, 'sale_discount', 'installed'),
(10, 'website_online', 'installed');
CREATE TABLE module_dependency(id integer, dependency_name text, module_id integer);
INSERT INTO module_dependency VALUES
(1, 'website_sale', 1),
(2, 'sale_bonus', 4),
(3, 'website_blog', 1),
(4, 'sale_discount', 4),
(5, 'website_online', 1),
(6, 'crm', 10),
(7, 'account', 3);
我尝试编写递归查询,但没有成功。看起来像无限循环。如果我可以获得模块 table 的所有模块 ID,我可以简单地更新选定的条目。
WITH RECURSIVE modules_to_upgrade AS
(
SELECT id
FROM module
WHERE name = 'website'
UNION ALL
SELECT md.module_id
FROM module_dependency md JOIN modules_to_upgrade mtu on mtu.id = md.module_id
)
select * from modules_to_upgrade;
为了 link 递归部分回到模块,你似乎不能使用依赖 ID。
所以它必须在名字上。
WITH RECURSIVE rcte_modules_to_upgrade AS ( SELECT m.id as module_id , m.name as module_name , md.id as dependency_id , md.dependency_name , m.id as base_module_id , 1 as depth FROM module m JOIN module_dependency md ON md.module_id = m.id WHERE m.name = 'website' UNION ALL SELECT m.id , m.name , md.id , md.dependency_name , rcte.base_module_id , rcte.depth + 1 FROM rcte_modules_to_upgrade rcte JOIN module m ON m.name = rcte.dependency_name LEFT JOIN module_dependency md ON md.module_id = m.id ) select * from rcte_modules_to_upgrade;
module_id | module_name | dependency_id | dependency_name | base_module_id | depth --------: | :------------- | ------------: | :-------------- | -------------: | ----: 1 | website | 1 | website_sale | 1 | 1 1 | website | 3 | website_blog | 1 | 1 1 | website | 5 | website_online | 1 | 1 6 | website_sale | null | null | 1 | 2 8 | website_blog | null | null | 1 | 2 10 | website_online | 6 | crm | 1 | 2 3 | crm | 7 | account | 1 | 3 5 | account | null | null | 1 | 4
WITH RECURSIVE rcte_modules_to_upgrade AS ( SELECT m.id as module_id , md.dependency_name FROM module m JOIN module_dependency md ON md.module_id = m.id WHERE m.name = 'website' UNION ALL SELECT m.id , md.dependency_name FROM rcte_modules_to_upgrade rcte JOIN module m ON m.name = rcte.dependency_name LEFT JOIN module_dependency md ON md.module_id = m.id ) update module set state = 'to upgrade' where id in (select distinct module_id from rcte_modules_to_upgrade);
6 rows affected
select * from module order by id;
id | name | state -: | :------------- | :---------- 1 | website | to upgrade 2 | purchase | installed 3 | crm | to upgrade 4 | sale | uninstalled 5 | account | to upgrade 6 | website_sale | to upgrade 7 | purchase_bonus | installed 8 | website_blog | to upgrade 9 | sale_discount | installed 10 | website_online | to upgrade
db<>fiddle here