【问题标题】:Tree with recursive and default具有递归和默认值的树
【发布时间】:2015-04-14 12:24:57
【问题描述】:

使用 Postgres。

我有一个pricelists

CREATE TABLE pricelists(
  id SERIAL PRIMARY KEY,
  name TEXT,
  parent_id INTEGER REFERENCES pricelists
);

另一个表,prices,引用它

CREATE TABLE prices(
  pricelist_id INTEGER REFERENCES pricelists,
  name TEXT,
  value INTEGER NOT NULL,
  PRIMARY KEY (pricelist_id, name)
);
  • 父价目表id=1 可能有 10 个价格。
  • 价格表id=2 作为父级1 的子级可能有5 个价格覆盖父级1 相同价格名称的价格。
  • 子价目表id=3 作为价目表2 的子价目,可能有2 个价格覆盖同价名的子价目表2

所以当我问孩子3价格时,我想得到

  • 所有儿童价格3
  • 他的父母(孩子2)在孩子3中不存在的价格和
  • 所有父级1 直到现在才存在的价格。

可以更改架构以提高效率。

示例:

如果

SELECT pl.id AS id, pl.parent_id AS parent, p.name AS price_name, value
FROM pricelists pl
JOIN prices p ON pl.id = p.pricelist_id;

给予

| id       |      parent   |  price_name |     value   |  
|----------|:-------------:|------------:|------------:|  
| 1        |  1            | bb          |     10      |  
| 1        |  1            | cc          |     10      |  
| 2        |  1            | aa          |     20      |  
| 2        |  1            | bb          |     20      |  
| 3        |  2            | aa          |     30      |

然后我正在寻找一种获取pricelist_id = 3 价格的方法

| id       |      parent   |  price_name |     value   |  
|----------|:-------------:|------------:|------------:|  
| 1        |  1            | cc          |     10      |  
| 2        |  1            | bb          |     20      |  
| 3        |  2            | aa          |     30      |

【问题讨论】:

  • 请一如既往地提供您的 Postgres 版本。 SELECT version()。并展示你尝试过的东西,即使它不起作用。
  • 示例中的价格表 1 是否应该将其自身作为父级,而不是 NULL

标签: sql postgresql greatest-n-per-group common-table-expression recursive-query


【解决方案1】:
WITH RECURSIVE cte AS (
   SELECT id, name, parent_id, 1 AS lvl
   FROM   pricelists
   WHERE  id = 3  -- provide your id here

   UNION ALL
   SELECT pl.id, pl.name, pl.parent_id, c.lvl + 1
   FROM   cte  c
   JOIN   pricelists pl ON pl.id = c.parent_id
   )
SELECT DISTINCT ON (p.price_name)
       c.id, c.parent_id, p.price_name, p.value
FROM   cte c
JOIN   prices p ON p.pricelist_id = c.id
ORDER  BY p.price_name, c.lvl;  -- lower lvl beats higher level

【讨论】:

  • 如果存在以自己为父项的价目表,则此查询不会终止,如问题中给出的示例所示。尽管我 guess 这可能是示例数据中的错误,或者被“可以更改架构以提高效率”所涵盖。短语。
  • @das-g。这是正确的。基表应该有一个约束CHECK (id <> parent_id)。并且根应该有parent_idNULL
  • 啊,对,这应该是一致性要求的一部分。我已经建议使用 CHECK 对问题进行编辑,尽管通常不足以避免价格表有向图中的循环。
  • @das-g:CHECK 约束只排除了简单的快捷循环。各种循环都会违反健全的数据模型。
  • 这就是我想在之前的评论中指出的。我只是说它太令人费解了,我猜。 :-P
猜你喜欢
  • 1970-01-01
  • 2011-05-12
  • 1970-01-01
  • 1970-01-01
  • 2014-10-24
  • 2012-03-23
  • 1970-01-01
  • 1970-01-01
  • 2020-03-01
相关资源
最近更新 更多