sql - 我可以在带有窗口功能的SQL查询中进行分组吗?

标签 sql oracle oracle11g

我需要让 员工在他们的部门中获得最低工资
我是用反连接做的。

     select emp.employee_id,emp.last_name,emp.salary,emp.department_id
     from employees emp
     left join employees sml 
     on sml.department_id = emp.department_id and sml.salary < emp.salary
     where sml.employee_id is null and emp.department_id is not null

但有人告诉我,可以使用窗口函数 使用一个选择 来做到这一点。
但是我不能按部门 ID 对其进行分组并同时使用它。
这是一个错误还是我愚蠢?
     SELECT  department_id,
     min(salary) OVER (partition by department_id)  as minsalary
     FROM employees;
     GROUP BY department_id

SQL Developer 说 00979. 00000 - “不是 GROUP BY 表达式”

最佳答案

如果您在没有group by的情况下运行第二个查询(您可能已经尝试过,从您发布的多余分号开始),您将看到每位雇员得到一行,每行显示其所在部门的最低工资。该最小值是解析min(),因为它具有window子句。 PARTITION BYGROUP BY等效,但没有对整个结果集进行汇总。

获得相同结果的最简单方法(几乎)是改为使用RANK()分析函数,该函数根据提供的分区和顺序对值进行排序,同时允许联系:

SELECT employee_id, last_name, salary, department_id,
  RANK() OVER (PARTITION BY department_id ORDER BY salary) AS rnk
FROM employees
ORDER BY department_id, rnk;

EMPLOYEE_ID LAST_NAME                     SALARY DEPARTMENT_ID        RNK
----------- ------------------------- ---------- ------------- ----------
        200 Whalen                          4400            10          1
        202 Fay                             6000            20          1
        201 Hartstein                      13000            20          2
        119 Colmenares                      2500            30          1
        118 Himuro                          2600            30          2
        117 Tobias                          2800            30          3
        116 Baida                           2900            30          4
        115 Khoo                            3100            30          5
        114 Raphaely                       11000            30          6
...
        102 De Haan                        17000            90          1
        101 Kochhar                        17000            90          1
        100 King                           24000            90          3
...

对于部门20和30,您可以看到排名1的行是最低工资。对于部门90,有两名排名第一的员工,因为他们的最低工资相同。

您可以将其用作内联 View ,并仅选择排名第一的行:
SELECT employee_id, last_name, salary, department_id
FROM (
  SELECT employee_id, last_name, salary, department_id,
    RANK() OVER (PARTITION BY department_id ORDER BY salary) AS rnk
  FROM employees
)
WHERE rnk = 1
ORDER BY department_id;

EMPLOYEE_ID LAST_NAME                     SALARY DEPARTMENT_ID
----------- ------------------------- ---------- -------------
        200 Whalen                          4400            10
        202 Fay                             6000            20
        119 Colmenares                      2500            30
        203 Mavris                          6500            40
        132 Olson                           2100            50
        107 Lorentz                         4200            60
        204 Baer                           10000            70
        173 Kumar                           6100            80
        101 Kochhar                        17000            90
        102 De Haan                        17000            90
        113 Popp                            6900           100
        206 Gietz                           8300           110
        178 Grant                           7000              

13 rows selected. 

如果您不必担心联系,那么还有一个更简单的选择,但这在这里不合适。

请注意,这比原始查询多了一行。您正在加入on sml.department_id = emp.department_id。如果部门ID为null(与员工178相同),则该连接失败,因为您无法使用相等性测试将null与null进行比较。由于此解决方案没有联接,因此不适用,并且您会在结果中看到该员工。

关于sql - 我可以在带有窗口功能的SQL查询中进行分组吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40594466/

相关文章:

sql - 如何覆盖 ORDER 方法 PL/SQL?

SQL Oracle 查询来比较公司每项工作的男性与女性薪资

php - 编辑表的特定字段

sql - 如何在 postgres 中的文本列上添加唯一约束(忽略特殊字符)?

java - 创建没有描述的 SchemaCrawler 图

oracle - 如何验证从外部数据库(oracle)到hdfs的数据传输

sql - Oracle SQL中结合LIMIT子句访问主表字段的子查询

mysql - 计算按足球队分组的胜利次数

sql - 如果一个表中的连接列可以有重复项,如何避免在使用左连接创建 View 时出现重复项?

c# - 存储在 oracle 中的 GUID/RAW 几乎匹配,除了最后 4 个字符