1. Problem
I have a self reference table through parent_id column.
The requirement is get all the children record of selected record.
The requirement is get all the children record of selected record.
2. Using recursion in sql (mysql >= 8.0)
def self.descendant
sql = <<-SQL
with recursive cte (id, parent_id) as (
select id, parent_id
from tables
where parent_id IN (#{ids.join(',')})
union all
select i.id, i.parent_id
from tables as i
inner join cte
on i.parent_id = cte.id
)
select id from cte
SQL
Table.execute_sql(sql).to_a.flatten
endThis command will self join until the join target table is empty.
3. The query structure
This query contains 3 parts:
- Anchor member: This is the initial query.
select id, parent_id
from tables
where parent_id IN (#{ids.join(',')})- Recursive query: This query will self join the previous result table (cte) with the original table.
select i.id, i.parent_id
from tables as i
inner join cte
on i.parent_id = cte.id- UNION ALL: Union the results to 1 final table.
First, the anchor member will return a table, this table will be used as recursive query params, after that the result of recursive query params will be the params of next recursive query, ...
It will stop if recursive query return empty table (the last recursive query return 0 record).
UNION ALL will be called and union all the tables to 1 final table.
Demo: Link
It will stop if recursive query return empty table (the last recursive query return 0 record).
UNION ALL will be called and union all the tables to 1 final table.
Demo: Link