SQL选择三级树中符合条件的所有节点

时间:2019-01-05 21:20:35

标签: postgresql

我有一个PostgreSQL模型(在Django的上下文中生成),看起来像这样:

CREATE TABLE org (
  id INTEGER NOT NULL,
  parent_id INTEGER,
  name CHARACTER VARYING(24),
  org_type  CHARACTER VARYING(8),
  country CHARACTER VARYING(2)
)

CREATE TABLE rate (
  id INTEGER NOT NULL,
  org_id INTEGER NOT NULL,
  rate DOUBLE PRECISION NOT NULL,
  currency CHARACTER VARYING(3)
)

其中org_type是“组”,“公司”和“分支”之一。每个分支都有一个公司,只有公司属于一个组。给定一个任意的公司或分支机构以及一个国家/地区,我需要找到所有org_id是属于同一组并且在指定国家/地区的公司和分支机构的org_id的费率。因此,在下图中,对于公司123(在加拿大)或分支机构124(在多伦多),搜索“国家/地区”为“美国”的费率将在标记为“选定”的框中找到属于公司或分支机构的费率:

enter image description here

我正在为公司尝试以下操作,其中$1是国家/地区代码,而$2是组织ID:

SELECT rate.org_id, rate.rate, rate.currency
FROM rate, org
WHERE (
  org.country = $1 AND
  rate.org_id=org.id AND
  org.parent_id = $2
) OR (
  ...

然后我陷入困境,试图弄清楚如何寻求属于我刚找到的公司之一的分支机构。我真的更喜欢一个大的WHERE子句,该子句可以带入任何相关组织的所有费率,这样我就不必对数据库进行一堆查询。

编辑

基于lau's answer,我尝试了一个示例(SQL fiddle),但这只是我刚开始的组织的回报率。

2 个答案:

答案 0 :(得分:1)

您可以:

  1. 就像您一样在org上应用条件
  2. 使用您的初始org作为起点,向上/向下浏览
  3. UNION组合2套
  4. JOIN和费率(下面我做了LEFT OUTER JOIN以便明确说明递归中确切包含的内容)。

示例:

WITH RECURSIVE SelectedOrg AS (
    SELECT * FROM org WHERE id = 4
),
BrowseOrg AS (
    SELECT 1 AS Direction, * FROM SelectedOrg
    UNION ALL
    SELECT -1, * FROM SelectedOrg
    UNION ALL
    SELECT Direction, org.* FROM org JOIN BrowseOrg ON (direction = 1 and org.parent_id = BrowseOrg.id) OR (direction = -1 and org.id = BrowseOrg.parent_id)
)
SELECT DISTINCT rates.id, BrowseOrg.id, rates.rate FROM BrowseOrg LEFT OUTER JOIN rates ON org_id = BrowseOrg.id

这将足够灵活以处理您不知道所选org级别(组,公司或分支机构)的情况。
将来,这也应该能够应付更深层次的层次结构(如果您向层次结构添加了层次)。

答案 1 :(得分:0)

您可以在2个查询中使用一些子查询来实现。

company_org_ids = select id from org where country code = $1 and parent_id = $2

Select distinct rate.* from rate where orgid in ($3) or where orgid in (select id from org where parent_id in $3 and country_code =$1)

这里$ 3是第一个查询的company_org_ids结果。

此外,也可以通过将$3变量替换为第一个查询来完成单个查询。