Using a WITH inside of a RECURSIVE WITH in PostgreSQL
Start with WITH RECURSIVE
. You can still add non-recursive CTEs:
WITH RECURSIVE
num AS (VALUES (50))
, num2 AS (SELECT column1 * 2 AS value FROM num)
, t(n) AS (
VALUES (1)
UNION ALL
SELECT n+1 FROM t WHERE n < (SELECT value FROM num2)
)
SELECT sum(n) FROM t;
sqlfiddle
See:
- How to use multiple CTEs in a single SQL query?
Recursion with postgresql query
This query should help. The first CTE ("with" part) provides all relations there are in the table. The second CTE filters only end child records out.
And the final part - the main query - searches for parents having 331 as a child and shows you those.
with recursive result_q as (
select 1 debug_step, parent_data, child_data
from data_rel
union all
select debug_step + 1, q.parent_data, r.child_data
from data_rel r
join result_q q
on q.child_data = r.parent_data
),
parent_end_childs as (
select q.parent_data, q.child_data
from result_q q
where not exists (select 1 from data_rel r where r.parent_data = q.child_data)
order by parent_data, child_data)
select pec.*
from parent_end_childs pec
join parent_end_childs pec_1
on pec.parent_data = pec_1.parent_data
where pec_1.child_data = 331
dbfiddle
SQL - WITH RECURSIVE doesn't work, when there is another query before
recursive
refers to the entire with
clause. So just use:
with recursive path as (<some other query>), -- 2
What recursive
really means is that Postgres will search for "table" names first as CTEs and then as tables/views in the recursive part of the CTE. The issue is really resolving identifiers. It has no effect on other CTEs.
Recursive PostgreSQL Query for Updating Column
To link the recursive part back to modules it seems you can't use the dependency id.
So it has to be on the names.
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
PostgreSQL recursive select find root element from leaf
With the current data structure, there is no other way than to visit the entire path from leaf to root. You can speed up this search a bit by operating only on key columns:
with recursive my_tree as (
select id, parent_id
from messages
where id = 9
union all
select m.id, m.parent_id
from messages m
join my_tree t on m.id = t.parent_id
)
select m.*
from messages m
join my_tree t using(id)
where t.parent_id is null
db<>fiddle.
If this solution is not satisfactory, you can consider adding a column to the table
alter table messages add root_id int;
Filling this column with a recursive query will be easy and you will have immediate access to the root of every node.
An alternative is to change the data structure using the ltree extension.
recursive query in postgres with a parameter in chain
You can provide the parameter in the root/anchor query of the CTE. But you need to select from the actual table in the recursive part:
WITH RECURSIVE chain AS (
select "applicationNodeInstanceId", "nextNodeInstanceId"
from appnodeinstance
where "applicationNodeInstanceId" = 'vc1' --<< this can be a parameter
UNION all
SELECT c."applicationNodeInstanceId", c."nextNodeInstanceId"
FROM appnodeinstance c
JOIN chain ani ON c."applicationNodeInstanceId" = ani."nextNodeInstanceId"
)
SELECT *
FROM chain;
Related Topics
Get Last Friday's Date Unless Today Is Friday Using T-Sql
SQL Query with Union in Doctrine Symfony
Set Identity_Insert Postgresql
Select the First 3 Rows of Each Table in a Database
Preserve Parent-Child Relationships When Copying Hierarchical Data
Sql: Try/Catch Doesn't Catch an Error When Attempting to Access a Table That It Can't Find
Go with SQL Server Driver Is Unable to Connect Successfully, Login Fail
Ssrs - Group_Concat Equivalent Using an Expression
Oracle SQL - Add Primary Key to Table
How to Match Multiple Column in a Table with SQLite Fts3
How to Determine the Primary Key for a Table in SQL Server
How to Migrate Datetime Values to Datetimeoffset in SQL Server
What Would Be the Best Way to Store Records Order in SQL
Table Valued Function Where Did My Query Plan Go
Characters That Must Be Escaped in T-Sql