Sql 如何使用递归查询获得平均值

Sql 如何使用递归查询获得平均值,sql,postgresql,Sql,Postgresql,我正在尝试使用postgres编写递归查询,其工作正常,并返回用户5下的所有用户,代码如下: WITH RECURSIVE subordinates AS ( SELECT id, supervisor_id, name FROM employees WHERE id = 5 UNION SELECT e.id, e.supervisor_id,

我正在尝试使用postgres编写递归查询,其工作正常,并返回用户5下的所有用户,代码如下:

WITH RECURSIVE subordinates AS (
   SELECT
      id,
      supervisor_id,
      name
   FROM
      employees
   WHERE
      id = 5
   UNION
      SELECT
         e.id,
         e.supervisor_id,
         e.name
      FROM
         employees e
      INNER JOIN subordinates s ON s.id = e.supervisor_id
) SELECT
   *
FROM
   subordinates;
但我还有一张叫做饼干的桌子,它有三列:类型、重量和烹调方式

现在,我需要id、姓名和主管id的饼干的平均重量,但有一个小小的转折点,如果用户id 1在3以下,3在4以下,4在5以下,那么它应该返回所有1、3、4和5由员工id记录烹调的饼干的平均重量,并且一个用户可以在饼干中有多个记录

我试过了,但没用

WITH RECURSIVE subordinates AS (
   SELECT
      e.id,
      e.supervisor_id,
      e.name,
   AVG(b.weight)
   FROM
      employees e
   LEFT JOIN burrito b ON 
   e.id=b.cooked_by_employee_id
   WHERE
      e.id = 5
   UNION
      SELECT
         e.id,
         e.supervisor_id,
         e.name,
   b.weight
      FROM
         employees e
      INNER JOIN subordinates s ON s.id = e.supervisor_id
      LEFT JOIN burrito b ON b.cooked_by_employee_id=e.supervisor_id
) SELECT
   *
FROM
   subordinates;
样本数据:

员工

+----+------+---------------+
| id | name | supervisor_id |
+----+------+---------------+
| 1  | a    | 3             |
+----+------+---------------+
| 2  | b    | 4             |
+----+------+---------------+
| 3  | c    | 5             |
+----+------+---------------+
| 4  | d    | 0             |
+----+------+---------------+
| 5  | e    | 0             |
+----+------+---------------+
+----+-------+--------+-----------------------+
| id | type  | weight | cooked_by_employee_id |
+----+-------+--------+-----------------------+
| 1  | sweet | 1      | 1                     |
+----+-------+--------+-----------------------+
| 2  | salty | 2      | 1                     |
+----+-------+--------+-----------------------+
| 3  | sweet | 3      | 3                     |
+----+-------+--------+-----------------------+
玉米煎饼

+----+------+---------------+
| id | name | supervisor_id |
+----+------+---------------+
| 1  | a    | 3             |
+----+------+---------------+
| 2  | b    | 4             |
+----+------+---------------+
| 3  | c    | 5             |
+----+------+---------------+
| 4  | d    | 0             |
+----+------+---------------+
| 5  | e    | 0             |
+----+------+---------------+
+----+-------+--------+-----------------------+
| id | type  | weight | cooked_by_employee_id |
+----+-------+--------+-----------------------+
| 1  | sweet | 1      | 1                     |
+----+-------+--------+-----------------------+
| 2  | salty | 2      | 1                     |
+----+-------+--------+-----------------------+
| 3  | sweet | 3      | 3                     |
+----+-------+--------+-----------------------+
因此,如果它为employee_id
5
运行,那么它应该返回

+-------------+------+-----------------------------------------------------+
| employee_id | name | weight                                              |
+-------------+------+-----------------------------------------------------+
| 5           | e    | 2 (Average 2 because both 1 and 3 id comes under 5) |
+-------------+------+-----------------------------------------------------+

你已经计算出了递归CTE,这可能是战斗的一半(或更多)。但是,以下内容构建了一个稍有不同的版本。递归cte(path_to_chef)获取员工ID并构建从顶层到员工的路径。然后,第二个cte(cook_chef)将路径字符串剥离回顶级员工id。结果包含两列,员工id和根级别员工的员工id。然后,这将设置阶段以与其他表连接以获得最终结果
通过在指定的位置提供id,该查询可以作为独立查询,也可以用于单个根级别。但我倾向于创建通用的可重用例程,所以我将其包装到了一个SQL函数中

create or replace function chef_avg_burrito_weight()
  returns table ( employee_id integer
                , name        text
                , weight      numeric
                ) 
  language sql 
 as $$ 
    with recursive path_to_chef as
         ( select id, trim(to_char(id, '9999'))||'>' path
             from employees
            where supervisor_id = 0
          union all 
          select e.id,  path || trim(to_char(e.id, '9999'))||'>'
          from employees e 
          join path_to_chef c on e.supervisor_id = c.id
         ) -- select * from path_to_chef
       , cook_chef as 
         (select id cook
               , substring(path from '^([[:digit:]]+)>')::integer chef 
            from path_to_chef
         ) -- select * from cook_chef        
    select e.id, e.name, round(avg(b.weight),2) average_weight
      from burrito b   
      join cook_chef c on (b.cooked_by_employee_id = c.cook) 
      join employees e on (e.id = c.chef)
      -- where chef = 5
     group by e.id, e.name;
$$;  

-- test 
select * 
  from chef_avg_burrito_weight()
 where employee_id = 5;

“样本数据和期望的结果将非常有用。@GordonLinoff添加了样本数据和期望的结果