【问题标题】:SQL tree recursive mean of children values子值的 SQL 树递归平均值
【发布时间】:2022-06-10 16:57:38
【问题描述】:

我目前正在设计一个目录系统。它有两种类型的项目:类别和项目本身。也可能存在嵌套类别,并且某些项目可能具有始终是某个类别的父项。
所以表格看起来像:

create table items
(
    id        uuid,
    parent    uuid,
    name      text,
    type      text,
    cost      int,

    primary key (id),
    constraint constraint_on_parent
        foreign key (parent)
            references items (id)
);

另外要提到的是,所有类别项目的成本都等于 null(好吧,毕竟,您不能自己购买类别,对吧?)。
现在我需要提出一个 sql 查询,如果它是一个类别,它会在给定项目 id 的情况下返回自身及其所有子项。另外,如果它是一个类别,那么我想获得其子类别的平均价格(也适用于子类别)。
到目前为止,我已经设法创建了一个递归查询来检索自身和孩子:

with recursive query as (
    select id, name, type, cost
    from items
    where id=$item_id
    union all
    select it.id, it.name, it.type, it.cost
    from items it inner join query q on q.id = it.parent
)
select id, name
from children

但是,现在我想知道,如何更改它以递归计算该类别及其子类别的平均价格?
另外,我使用的是 PostgreSQL 14。

编辑 1:示例数据和所需输出
示例数据

id parent name type cost
uuid1 null root category null
uuid2 uuid1 item1 item 100
uuid3 uuid1 subcategory1 category null
uuid4 uuid3 item2 item 200
uuid5 uuid3 item3 item 300

所需的输出
当对 uuid3 运行描述的查询时,我希望得到类似

id parent name type cost
uuid3 uuid1 subcategory1 category 250
uuid4 uuid3 item2 item 200
uuid5 uuid3 item3 item 300

此输出看起来像样本数据的最后 3 行,除了第一行,即类别,其价格等于其子项的平均价格
当对 uuid1 运行所描述的查询时,我希望得到

id parent name type cost
uuid1 null root category 200
uuid2 uuid1 item1 item 100
uuid3 uuid1 subcategory1 category 250
uuid4 uuid3 item2 item 200
uuid5 uuid3 item3 item 300

这里subcategory1 价格是item2item3 成本的平均值,root 价格是item1item2items3 成本的平均值。
此外,如果该类别中没有商品,则其价格应保持为空

【问题讨论】:

  • 样本数据和所需的输出会有所帮助。
  • @Serg 更新了问题

标签: sql postgresql recursion common-table-expression window-functions


【解决方案1】:

您可以使用 ARRAY 来存储项目的路径

with recursive query as (
    select id, name, type, cost, array[id] path
    from items
    where id='uuid1'
    union all
    select it.id, it.name, it.type, it.cost, array_append(path, it.id)
    from items it inner join query q on q.id = it.parent
)
select  t1.id, t1.name, t1.type, avg(t2.cost) cost
from query t1
left join query t2 on t2.path @> Array[t1.id]
group by t1.id, t1.name, t1.type;

db<>fiddle

返回

id  name    type    cost
uuid1   root    category    200.0000000000000000
uuid2   item1   item    100.0000000000000000
uuid3   subcategory1    category    250.0000000000000000
uuid4   item2   item    200.0000000000000000
uuid5   item3   item    300.0000000000000000

【讨论】:

    猜你喜欢
    • 2022-06-12
    • 1970-01-01
    • 1970-01-01
    • 2017-07-25
    • 2018-01-05
    • 2019-09-24
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多