Postgresql

在 Postgres 11 中的第一個匹配項上停止遞歸查詢

  • September 16, 2022

我在 Postgres 中的遞歸查詢有點掙扎。

鑑於這些表:

create table resource_v3
(
   id            uuid not null primary key,
   name          varchar(255),
   resource_id   uuid,
   resource_type varchar(255),
   tenant_id     uuid
);

create table resource_associations
(
   parent_id uuid not null
   child_id  uuid not null
   primary key (parent_id, child_id)
);

鑑於這些表,我建構了以下結構

在此處輸入圖像描述

我要存檔的是獲取 user1 所在的所有團隊或組織。我只需要第一個匹配項,因此給定 user1 遞歸應該在“團隊服務技術人員”和“ORG:Seepex”處停止。它不應該返回“ORG:CS”而不是“ORG:Seepex-UK”

我的查詢:

WITH RECURSIVE c AS (
  SELECT v.id from resource_v3 v where v.resource_id = '8a84bf66-6dc4-43c7-ace1-d104fddaa1be'

  UNION ALL

  SELECT sa.parent_id
  FROM resource_associations AS sa JOIN c ON c.id = sa.child_id
      JOIN resource_v3 rv3 on c.id = rv3.id
   WHERE rv3.resource_type != 'TEAM' OR rv3.resource_type != 'ORGANISATION'
)
SELECT r.* FROM c JOIN resource_v3 r ON c.id=r.id;

如我所料返回更多數據:

在此處輸入圖像描述

我在這裡做錯了什麼或者你將如何解決這個問題?似乎我幾乎在那裡,查詢應該在第一次命中時停止向上移動。

我的最終目標是獲取給定使用者所在的 TEAM 或 ORGANIZATION 的所有子元素。因此,邏輯計劃是使用上面的查詢獲取組織/團隊,然後從那裡遞歸獲取子元素,這相當容易並且運作良好。

嘗試以下查詢。WHERE c.resource_type NOT IN ('TEAM', 'ORGANISATION')訣竅是如果您還沒有通過在 CTE 的遞歸部分中使用找到 TEAM 或 ORGANIZATION 項,則繼續向上鍊。

WHERE c.resource_type IN ('TEAM', 'ORGANISATION')如果您只想返回找到的頂部(TEAM 或 ORGANIZATION)項目而不返回起點(User1)或不同資源類型的可能中間項目,則需要外部查詢。

WITH RECURSIVE c AS (
  SELECT v.id, v.resource_type 
  from resource_v3 v 
  where v.resource_id = '8a84bf66-6dc4-43c7-ace1-d104fddaa1be'

  UNION ALL

  SELECT sa.parent_id, rv3.resource_type
  FROM resource_associations AS sa 
       JOIN c ON c.id = sa.child_id
       JOIN resource_v3 rv3 on sa.parent_id = rv3.id
  WHERE c.resource_type NOT IN ('TEAM', 'ORGANISATION')
)
SELECT r.* 
FROM c JOIN resource_v3 r ON c.id = r.id
WHERE c.resource_type IN ('TEAM', 'ORGANISATION') ;

引用自:https://dba.stackexchange.com/questions/316975