oracle 分析函数和普通SQL等效函数

wnrlj8wa  于 2022-11-22  发布在  Oracle
关注(0)|答案(4)|浏览(163)

我正在使用Oracle和SQL Developer。我已经下载了HR schema,需要用它来做一些查询。现在我正在使用表Employees。作为用户,我需要看到每个部门中工资最低的员工列表。我需要通过普通SQL和一个分析函数来提供不同的解决方案。关于分析函数,我使用了RANK()

SELECT *
FROM
    (SELECT
         employee_id,
         first_name,
         department_id,
         salary,
         RANK() OVER (PARTITION BY department_id 
                      ORDER BY salary) result
     FROM
         employees)
WHERE 
    result = 1 
    AND department_id IS NOT NULL;

结果似乎正确:

但当我尝试使用普通SQL时,我实际上得到了所有雇员及其薪水。
下面是我对GROUP BY的尝试:

SELECT 
    department_id, MIN(salary) AS "Lowest salary"
FROM 
    employees
GROUP BY 
    department_id;

这段代码看起来不错,但我还需要获取first_nameemployee_id列。
我试着做这样的事情:

SELECT
    employee_id,
    first_name,
    department_id,
    MIN(salary) result
FROM
    employees
GROUP BY
    employee_id,
    first_name,
    department_id;

以及以下内容:

SELECT
    employee_id,
    first_name,
    salary,
    departments.department_id
FROM
    employees
LEFT OUTER JOIN 
    departments ON (employees.department_id = departments.department_id)
WHERE
    employees.salary = (SELECT MIN(salary)
                        FROM departments 
                        WHERE department_id = employees.department_id)

这些似乎是错误的。我如何改变或修改我的查询以获得与通过普通SQL使用RANK()时相同的结果(至少有两种解决方案)?

uplii1fm

uplii1fm1#

其中一个选项可以像这里(与旧EMP表)...

SELECT EMPNO, ENAME, DEPTNO, SAL
FROM   EMP e
WHERE  SAL = (Select MIN_SAL From (SELECT DEPTNO, Min(SAL) "MIN_SAL"
                                    FROM   EMP
                                    GROUP BY DEPTNO) 
              Where DEPTNO = e.DEPTNO)
ORDER BY DEPTNO, SAL;

第二个选择可能是...

SELECT EMPNO, ENAME, DEPTNO, SAL
FROM   (SELECT e.EMPNO, e.ENAME, e.DEPTNO, e. SAL, (Select Min(SAL) "MIN_SAL" From EMP Where DEPTNO = e.DEPTNO) "MIN_SAL" From EMP e) 
WHERE  SAL = MIN_SAL
ORDER BY DEPTNO, SAL;

此致

e5nszbig

e5nszbig2#

您可以使用子查询查找每个雇员的最低薪金,并使用主查询仅显示由该子查询选择的那些雇员的信息:

SELECT 
employee_id,
first_name,
department_id,
salary
FROM employees e1
WHERE salary =
(SELECT MIN(e2.salary)
FROM employees e2
WHERE e1.employee_id = e2.employee_id);

这将产生与RANK查询完全相同的结果。
我认为应用一些查询中缺少的排序是有意义的。我不知道你想如何排序,但这里有一个按雇员姓名排序的示例:

SELECT 
employee_id,
first_name,
department_id,
salary
FROM employees e1
WHERE salary =
(SELECT MIN(e2.salary)
FROM employees e2
WHERE e1.employee_id = e2.employee_id)
ORDER BY first_name;

既然您要求至少提供两种解决方案,那么让我们来看看另一个选项:

SELECT 
e1.employee_id,
e1.first_name,
e1.department_id,
e1.salary
FROM employees e1
JOIN (
SELECT employee_id, MIN(salary) salary
FROM employees
GROUP BY employee_id ) e2
ON e1.employee_id = e2.employee_id AND e1.salary = e2.salary
ORDER BY first_name;

正如您所看到的,这是不同的,因为子查询将应用GROUP BY子句,并且它可以作为自己的查询成功执行,而这对于前一个查询中使用的子查询是不可能的。
然后,主查询的JOIN将确保再次获得所需的结果。

2uluyalo

2uluyalo3#

以下是获取部门中最低薪金的员工的一些选项:

最低工资超过(...)

select employee_id, first_name, department_id, salary
from
(
  select e.*, min(salary) over (partition by department_id) as min_sal
  from employees e
)
where sal = min_sal;

使用RANK和FETCH FIRST

select *
from employees
order by rank() over (partition by department_id order by salary)
fetch first row with ties;

带IN

select *
from employees
where (department_id, salary) in
(
  select department_id, min(salary)
  from employees
  group by department_id
);

不存在

select *
from employees e
where not exists
(
  select null
  from employees other
  where other.department_id = e.department_id
  and other.salary < e.salary
);
iqih9akk

iqih9akk4#

如果每个部门只有一个人的最低薪金,则可以使用KEEP

SELECT department_id,
       MIN(employee_id) KEEP (DENSE_RANK FIRST ORDER BY salary) AS employee_id,
       MIN(first_name) KEEP (DENSE_RANK FIRST ORDER BY salary, employee_id) AS first_name,
       MIN(salary) AS min_salary
FROM   employees
GROUP BY department_id

其中,对于示例数据:

CREATE TABLE employees (employee_id, department_id, first_name, salary) AS
SELECT 1, 1, 'Alice', 1000 FROM DUAL UNION ALL
SELECT 2, 1, 'Betty', 2000 FROM DUAL UNION ALL
SELECT 3, 2, 'Carol', 3000 FROM DUAL UNION ALL
SELECT 4, 2, 'Debra', 3000 FROM DUAL UNION ALL
SELECT 5, 2, 'Emily', 4000 FROM DUAL;

输出:
| 部门标识|员工标识|名字|最低薪金|
| - -|- -|- -|- -|
| 一个|一个|爱丽斯|千|
| 2个|三个|卡罗尔|三千|

  • 注:这将不匹配Debra,即使她在部门2中的薪金也是最低的,因为它将只查找具有最低薪金和最小雇员标识的单个雇员。*

如果您可以让多个员工具有相同的部门最低工资,则可以使用相关子查询:

SELECT department_id,
       employee_id,
       first_name,
       salary
FROM   employees e
WHERE  EXISTS(
         SELECT 1
         FROM   employees x
         WHERE  e.department_id = x.department_id
         HAVING MIN(x.salary) = e.salary
       );

对于样本数据,输出:
| 部门标识|员工标识|名字|薪金|
| - -|- -|- -|- -|
| 一个|一个|爱丽斯|千|
| 2个|三个|卡罗尔|三千|
| 2个|四个|黛布拉|三千|
这确实返回了黛布拉。
fiddle

相关问题