PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Откриване на дублиращи се елементи в рекурсивния CTE

Думата dep във втората заявка (след union ) е двусмислено. Всъщност тя се интерпретира като колоната на rdeps , а не като псевдоним на objectdependencies.

with recursive rdeps as (
  select dep
  from objectdependencies dep
  where dep.dependson = 4 -- starting point
  union all
  select dep -- this means r.dep
  from objectdependencies dep
  join rdeps r
    on (r.dep).id = dep.dependson
) select (dep).id from rdeps;

Ето защо заявката създава безкраен цикъл. Можете да коригирате това, като промените псевдонима:

with recursive rdeps as (
  select dep
  from objectdependencies dep
  where dep.dependson = 4 -- starting point
  union all
  select objectdep
  from objectdependencies objectdep
  join rdeps r
    on (r.dep).id = objectdep.dependson
) select (dep).id from rdeps;

 id 
----
  1
  2
  3
  1
  2
  1
(6 rows)    

Или по-добре, просто като използвате колони, както е замислил добрият Господ:

with recursive rdeps as (
    select id, dependson
    from objectdependencies
    where dependson = 4
union all
    select d.id, d.dependson
    from objectdependencies d
    join rdeps r
    on r.id = d.dependson
) 
select *
from rdeps;

Първата заявка във въпроса е всичко, което можете да направите в обикновен sql, тъй като няма комуникация между различни (паралелни) клонове, генерирани от рекурсивна заявка. При функционален подход можете да използвате временна таблица като общ магазин за всички клонове. Функцията може да изглежда така:

create or replace function rec_function(int)
returns void language plpgsql as $$
declare
    i int;
begin
    for i in
        select id
        from objectdependencies
        where dependson = $1
    loop
        if not exists(
            select from temp_table 
            where id = i)
        then
            insert into temp_table values(i);
            perform rec_function(i);
        end if;
    end loop;
end $$;

Употреба:

create temp table temp_table(id int);

select rec_function(4);

select *
from temp_table;


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Не може да се намери входна точка с име 'InterlockedIncrement' в DLL 'kernel32.dll' - [имейл защитен] 64 бита

  2. Индекс на долните букви на Flask-SQLAlchemy - функция за пропускане, не се поддържа от отражението на SQLAlchemy

  3. Как да приложим функция към всеки елемент от колона на масив в Postgres?

  4. Регистриране на одит за PostgreSQL

  5. Now() без часова зона