oracle SQL中连接操作

gstyhher  于 2022-12-18  发布在  Oracle
关注(0)|答案(3)|浏览(156)

有这样一个任务:通过连接表HR.DEPARTMENTS和HR.EMPLOYEES,显示最低工资低于5000的部门的完整数据。
我尝试过这样做,但它给出了一个错误

select distinct d.department_id,department_name, 
       d.manager_id, location_id 
from hr.departments d 
left join hr.employees e on e.department_id = d.department_id
where min(e.salary) < 5000 
order by 1

错误:此处不允许使用组函数
这是HR员工的样子:

EMPLOYEE_ID FIRST_NAME LAST_NAME EMAIL PHONE_NUMBER HIRE_DATE JOB_ID SALARY COMMISSION_PCT MANAGER_ID DEPARTMENT_ID
    100 Steven King SKING 515.123.4567 17-JUN-03 AD_PRES 24000 - - 90

hr.departments:

DEPARTMENT_ID DEPARTMENT_NAME MANAGER_ID LOCATION_ID
10 Administration 200 1700

kx7yvsdv

kx7yvsdv1#

不能在WHERE子句中使用MIN,因为MIN是多行的聚合结果,但在WHERE子句中,您查看的是单行(在进行任何聚合之前)。
通过连接表来获取相关部门的任务有点奇怪,因为这不是SQL中应该采用的方式。如果必须采用这种方式,那么只需对查询进行细微的更改:将联接更改为内部联接并检查行的薪金。

select distinct
  d.department_id, department_name, d.manager_id, location_id 
from hr.departments d 
join hr.employees e on e.department_id = d.department_id
where e.salary < 5000 
order by d.department_id;

正确的解决方案应该使用EXISTSIN,这样就不会创建一个不必要的大中间结果,而必须使用DISTINCT将其删除:

select *
from hr.departments
where department_id in (select department_id from employees where salary < 5000)
order by department_id;

select *
from hr.departments d
where exists
(
  select null
  from employees e
  where e.salary < 5000
  and e.department_id = d.department_id
)
order by department_id;

e4eetjau

e4eetjau2#

这适用于您的解决方案,其中用于行筛选,如gender = 'Male',而用于聚合筛选函数,如min(salary)〈5000,但对于,您需要使用诸如department之类的分组依据。

SELECT 
    *
FROM 
    DimEmployee
WHERE
    EmployeeID IN (
        SELECT 
            EmployeeID
        FROM
            DimEmployee
        GROUP BY
            EmployeeID
        HAVING  
            MIN(Salary) < 5000
    )
iklwldmw

iklwldmw3#

首先,不要使用distinct,除非你必须这样做。其次,你不能像那样使用group函数。
为了解决这个问题,你需要把任务分解成几个步骤,把你的句子分解。
1.“......table”
所以我们有这个:

SELECT * FROM hr.departments;

还有...

SELECT * FROM hr.employees;

1.“人力资源部门和人力资源员工”
正如你指出的,FK是部门。
(we首先测试连接,然后添加我们需要的内容)(1只是一个占位符;您可以使用员工ID或COUNT(1),这是不相关的)

SELECT 1 
 FROM hr.employees e
 LEFT JOIN hr.departments d on e.department_id = d.department_id;


1.“显示部门的完整数据”
这很简单,你只需要枚举你需要的列或者使用d.*
1.“最低工资低于5000”
现在我们来讨论阻塞问题。让我们列出记录。

SELECT d.*
 FROM hr.employees e, hr.departments d 
 WHERE e.department_id = d.department_id
 AND EXISTS (SELECT 1 FROM hr.employees m WHERE m.department_id = d.department_id GROUP BY m.department_id HAVING min(m.salary) < 5000);

但是这是什么呢?我们为该部门的每个雇员都设置了一行。我们可以使用DISTINCT,但这是一个不好的做法,或者我们可以修复查询。
我们将从联接中删除雇员。

SELECT d.*
 FROM hr.departments d 
 WHERE EXISTS (SELECT 1 FROM hr.employees e WHERE e.department_id = d.department_id GROUP BY e.department_id HAVING min(e.salary) < 5000);

更新:
1.为了遵守“通过连接表”的任务
所以我们有这个:

SELECT d.*
FROM hr.departments d,
(
    SELECT e.department_id
    FROM   hr.employees e
    GROUP  BY e.department_id
    HAVING min(salary) < 5000
) e
WHERE e.department_id = d.department_id;

相关问题