使用 SQL 上的两个表进行递归查询的正确顺序是什么?

What is the correct order for recursive queries using two tables on SQL?

我有以下两个表:

CREATE TABLE empleados (
  id INTEGER PRIMARY KEY,
  nombre VARCHAR(255) NOT NULL,
  gerenteId INTEGER,
  FOREIGN KEY (gerenteId) REFERENCES empleados(id)
);

CREATE TABLE ventas (
  id INTEGER PRIMARY KEY,
  empleadoId INTEGER NOT NULL,
  valorOrden INTEGER NOT NULL,
  FOREIGN KEY (empleadoId) REFERENCES empleados(id)
);

具有以下数据:

INSERT INTO empleados(id, nombre, gerenteId) VALUES(1, 'Roberto', null);
INSERT INTO empleados(id, nombre, gerenteId) VALUES(2, 'Tomas', null);
INSERT INTO empleados(id, nombre, gerenteId) VALUES(3, 'Rogelio', 1);
INSERT INTO empleados(id, nombre, gerenteId) VALUES(4, 'Victor', 3);
INSERT INTO empleados(id, nombre, gerenteId) VALUES(5, 'Johnatan', 4);
INSERT INTO empleados(id, nombre, gerenteId) VALUES(6, 'Gustavo', 2);

INSERT INTO ventas(id, empleadoId, valorOrden) VALUES(1, 3, 400);
INSERT INTO ventas(id, empleadoId, valorOrden) VALUES(2, 4, 3000);
INSERT INTO ventas(id, empleadoId, valorOrden) VALUES(3, 5, 3500);
INSERT INTO ventas(id, empleadoId, valorOrden) VALUES(4, 2, 40000);
INSERT INTO ventas(id, empleadoId, valorOrden) VALUES(5, 6, 3000);

我正在尝试查询以获取直接或间接属于主要经理的所有“订单”的总和。主要经理是那些不向其他任何人报告的人。在这种情况下,罗伯托和托马斯是主要经理,但可能还有其他人。结果必须不仅要考虑他直接进行的销售 (ventas),还要考虑他们的任何员工(直接员工或他们员工的员工)。

所以在这种情况下,我期待以下结果:

-- Id    TotalVentas
-- ----------------
-- 1     6900               
-- 2     43000

其中 Id 列是指“主要”经理的员工 ID,TotalVentas 列是他们及其员工所做的所有 ventas (valorOrden) 的总和。

所以 Roberto 没有订单记录,但 Rogelio(他的员工)有一个 400,Victor(Rogelio 的员工)有一个 3000,Johnatan(Victor 的员工)有另一个 3500。所以他们的总和是6900。和Tomas一样,有一个venta是他直接做的,还有一个是他的雇员Gustavo做的。

我目前的查询如下:

WITH cte_org AS (
    SELECT       
        id, 
        nombre,
        gerenteId,
        0 as EmpLevel
        
    FROM       
        dbo.empleados
    WHERE gerenteId IS NULL
    UNION ALL
    SELECT 
        e.id, 
        e.nombre,
        e.gerenteId,
        o.EmpLevel + 1
    FROM 
        dbo.empleados e
        INNER JOIN cte_org o 
            ON o.id = e.gerenteId
        WHERE e.gerenteId IS NOT NULL
)
SELECT cte.id, SUM(s.orderValue)
FROM cte_org cte, dbo.sales s
WHERE (cte.id = s.employeeId AND cte.gerenteId is null)
        OR
        (cte.id = s.employeeId AND cte.EmpLevel <> 0 AND
            cte.gerenteId in (select ee.id from dbo.empleados ee where ee.gerenteId is null)
        )
        --AND 
        --(cte.gerenteId in (select ee.id from dbo.empleados ee where ee.gerenteId is null)
        --OR
        --cte.gerenteId is null)
        
--AND cte.gerenteId = NULL
group by cte.id
;

有人可以帮我解决这个问题吗?

在 Oracle 中,您可以使用以下查询来执行此操作:

SQLFiddle

  select manager, sum(amount) as total_amount from 
(
select level, CONNECT_BY_ROOT employeeid Manager, a.* from 
  (
  SELECT a.id as employeeid, a.nombre as name , a.GERENTEID as manager_id, 
  b.EMPLEADOID as sales_id, b.VALORORDEN amount 
   from empleados a left outer join ventas b
  on (a.id = b.empleadoId)
  ) a
start with manager_id is null
connect by prior employeeid = manager_id) x 
group by manager;

这是遍历层次结构,从最高级别的经理开始,然后加入销售人员:

with cte as (
      select id, nombre, id as manager
      from empleados e
      where gerenteid is null
      union all
      select e.id, e.nombre, cte.manager
      from cte join
           empleados e
           on cte.id = e.gerenteid
     )
select cte.manager, sum(valororden)
from cte join
     ventas v
     on cte.id = v.empleadoid
group by cte.manager;

Here 是一个 db<>fiddle。 Fiddle 使用 SQL 服务器,因为这与您使用的语法一致。