首页 > 解决方案 > 如何访问相关子查询中的列

问题描述

使用以下数据,我试图获取具有相同位置和部门的员工,其类型为经理,其工资等于其他员工的总和 sal 以及 emp id,因为 empid 是不相等的查询不返回任何结果也分组查询应该有超过 1 条记录所以结果不应该包括 Raghu 记录,而且我想要所有匹配记录的 emp id:

  EMP_ID  EMP_Name    EMP_Loc EMP_Dept    EMP_Sal Emp_type
     1      Arjun       Hyd     Comp        1000    Manager
     2      Ramesh      Hyd     Comp        500     Interim
     3     Ragav       Hyd     Comp        300     Interim
     4     Rajesh      Hyd     Comp        200     Interim
     5     Raghu       Hyd     Comp        1000    Interim




 select  a.emp_dept , a.emp_loc ,a.emp_dept,b.emp_dept,a.emp_id,b.emp_id
     from  
     (select sum(emp_sal) as sett,emp_loc,emp_dept,emp_id
                   from employee 
                   where emp_type = 'Interim'
                   group by emp_loc,emp_dept,emp_id having count(emp_sal)>1
                  ) a
                  inner join 
                  (select emp_sal ,emp_loc,emp_dept,emp_id
                   from employee 
                   where emp_type = 'Manager'
                  ) b 
     on a.sett=b.emp_sal and a.emp_loc=b.emp_loc and a.emp_dept=b.emp_dept;

标签: sqlpostgresql

解决方案


您的问题是您将 emp_id 包含在您的第一个子选择中并对其进行分组。这意味着你得到三行,总和变得毫无意义。从来没有经理有 500、200 或 300 薪水的情况,因此连接不起作用,因此没有返回记录。如果你这样做,它应该工作:

select  a.emp_dept, a.emp_loc, b.emp_id
     from  
     (select sum(emp_sal) as sett,emp_loc,emp_dept
                   from employee 
                   where emp_type = 'Interim' and emp_sal > 1
                   group by emp_loc,emp_dept
                  ) a
                  inner join 
                  (select emp_sal ,emp_loc,emp_dept,emp_id
                   from employee 
                   where emp_type = 'Manager'
                  ) b 
     on a.sett=b.emp_sal and a.emp_loc=b.emp_loc and a.emp_dept=b.emp_dept;

请注意,我还删除了结果集中的重复列。显示 b.emp_dept 和 a.emp_dept 是没有意义的,因为连接条件保证它们是相同的。

编辑

在您对问题进行修改后,我现在了解您要做什么。这真的很难实现,因为您需要做的是对一个地点和部门的所有可能的临时工资进行笛卡尔总和,以检查工资总和的任何可能组合是否与经理的组合匹配。

一种可能的方法是:

WITH cte as
(SELECT a.emp_id as aempid, b.emp_id as bempid, 0 as cempid, 0 as dempid, a.emp_sal + b.emp_sal AS SumSal, a.emp_loc, a.emp_dept
FROM employee a
CROSS JOIN employee b WHERE a.emp_loc = b.emp_loc AND a.emp_dept = b.emp_dept
AND a.emp_type = b.emp_type AND a.emp_type = 'Interim' AND a.emp_id <> b.emp_id
AND b.emp_id > a.emp_id
UNION
SELECT a.emp_id, b.emp_id, c.emp_id, 0, a.emp_sal + b.emp_sal + c.emp_sal  AS SumSal, a.emp_loc, a.emp_dept
FROM employee a
CROSS JOIN employee b 
CROSS JOIN employee c
WHERE a.emp_loc = b.emp_loc AND a.emp_dept = b.emp_dept
AND a.emp_type = b.emp_type AND a.emp_type = 'Interim' AND a.emp_id <> b.emp_id
AND a.emp_loc = c.emp_loc AND a.emp_dept = c.emp_dept
AND a.emp_type = c.emp_type AND a.emp_id <> c.emp_id AND b.emp_id <> c.emp_id
AND b.emp_id > a.emp_id AND c.emp_id > b.emp_id
UNION
SELECT a.emp_id, b.emp_id, c.emp_id, d.emp_id, a.emp_sal + b.emp_sal + c.emp_sal + d.emp_sal AS SumSal, a.emp_loc, a.emp_dept
FROM employee a
CROSS JOIN employee b 
CROSS JOIN employee c
CROSS JOIN employee d
WHERE a.emp_loc = b.emp_loc AND a.emp_dept = b.emp_dept
AND a.emp_type = b.emp_type AND a.emp_type = 'Interim' AND a.emp_id <> b.emp_id
AND a.emp_loc = c.emp_loc AND a.emp_dept = c.emp_dept
AND a.emp_type = c.emp_type AND a.emp_id <> c.emp_id AND b.emp_id <> c.emp_id
AND a.emp_loc = d.emp_loc AND a.emp_dept = d.emp_dept
AND a.emp_type = d.emp_type AND a.emp_id <> d.emp_id AND b.emp_id <> d.emp_id AND c.emp_id <> d.emp_id
AND b.emp_id > a.emp_id AND c.emp_id > b.emp_id AND d.emp_id > c.emp_id
)
SELECT m.emp_id as managerid, cte.aempid, cte.bempid, cte.cempid, cte.dempid, m.emp_sal, m.emp_loc, m.emp_dept
FROM employee m 
INNER JOIN cte ON cte.emp_loc = m.emp_loc AND cte.emp_dept = m.emp_dept AND m.emp_sal = cte.sumsal
WHERE m.emp_type = 'Manager';

这真的很难看,但我想不出更好的了,至少它返回了预期的结果。当然,在实践中,您必须动态创建它以匹配任何一个地点/部门的临时员工的最大数量。

几点,以防不清楚。使用这种方法不需要 a,HAVING COUNT(*) > 1因为要求 a.emp_id <> b.emp_id 等保证至少有两个不同的临时雇员。还要求 b.emp_id > a.emp_id(以及 c 和 d)以确保 a、b、c 和 d 的每个可能组合只出现一次(所以在这种情况下,我们只得到 2、3、4(按此顺序)加上 0 表示 d,而不是 2、3 和 4 的所有可能组合。


推荐阅读