Рекурсивный запрос в MySQL 8.0 с динамическими именами таблиц - PullRequest
1 голос
/ 30 октября 2019

У меня есть две таблицы, одна из них sections, это id, parent_table и parent_id, другая pages, которая имеет id и status (и другие) столбцы. Родителем раздела может быть другой раздел или страница с соответствующими значениями parent_table. Как я могу узнать с помощью оконных функций, находится ли данный раздел на странице status = 1 или нет? (используя MySQL 8.0 (или MariaDB 10.2), но в крайнем случае я мог бы преобразовать в postgresql, если это крайне необходимо).

Пример данных:

секции

id|parent_table|parent_id
1 |pages       |1
2 |sections    |1
3 |pages       |2
4 |sections    |2

страницы

id|status
 1|1
 2|0

Чтобы воссоздать пример данных:

create table pages (id int not null primary key, status int not null) collate utf8mb4_general_ci;
create table sections (id int not null primary key, parent_table varchar(20), parent_id int not null) collate utf8mb4_general_ci;
insert into pages values (1,1),(2,0);
insert into sections values (1,'pages',1),(2,'sections',1),(3,'pages',2),(4,'sections',2);

Ответы [ 2 ]

1 голос
/ 07 ноября 2019

Чтобы получить соответствующий статус страницы для всех разделов, вы можете использовать следующий рекурсивный запрос:

with recursive r as (
  select s.id as section_id, s.parent_id, s.parent_table
  from sections s
  union all
  select r.section_id, s.parent_id, s.parent_table
  from r
  join sections s on s.id = r.parent_id and r.parent_table = 'sections'
)
select r.section_id, p.id as page_id, p.status
from r
join pages p on p.id = r.parent_id
where r.parent_table = 'pages';

Результат:

| section_id | page_id | status |
| ---------- | ------- | ------ |
| 1          | 1       | 1      |
| 2          | 1       | 1      |
| 4          | 1       | 1      |
| 3          | 2       | 0      |

Просмотр в БД Fiddle

Рекурсия проходит по дереву из любого раздела в его корневой раздел. Таким образом, вы можете ограничить результат одним разделом во внутреннем запросе. Например. если вы хотите узнать только состояние раздела 3, вы должны использовать предложение WHERE в первой части UNION RCTE:

with recursive r as (
  select s.id as section_id, s.parent_id, s.parent_table
  from sections s
  where s.id = 3 -- limit to a single section
  union all
  select r.section_id, s.parent_id, s.parent_table
  from r
  join sections s on s.id = r.parent_id and r.parent_table = 'sections'
)
select r.section_id, p.id as page_id, p.status
from r
join pages p on p.id = r.parent_id
where r.parent_table = 'pages';

Результат:

| section_id | page_id | status |
| ---------- | ------- | ------ |
| 3          | 2       | 0      |

Посмотреть на БД Fiddle

0 голосов
/ 07 ноября 2019

Без функции Windows SQL-запрос будет выглядеть следующим образом

SQL-запрос:

SELECT *
FROM sections WHERE parent_table = 'pages'  and parent_id IN
(SELECT id FROM pages WHERE pages.status= 1)

С функцией Windows код будет выглядеть следующим образом:

declare @parent_table varchar(5)
declare @status int
set @status=1;
set @parent_table='pages';
with pages as (
/* Anchor member */
select s.id, s.parent_table, s.parent_id 
from sections s
where s.parent_table=@parent_table
UNION ALL
/* Recursive Member */
select s.id, s.parent_table, s.parent_id, 
from sections s
join pages on
    s.parent_table=@parent_table and s.parent_id=pages.id)
select status from pages where status=1
option(MAXRECURSION 500)

Мы можем установить MAXRECURSION между 1 и 32767

...