programing

윈도우 기능이 있는 SQL 쿼리에서 그룹화할 수 있습니까?

mytipbox 2023. 8. 6. 15:06
반응형

윈도우 기능이 있는 SQL 쿼리에서 그룹화할 수 있습니까?

부서에서 월급이 가장 적은 직원들을 고용해야 합니다. 안티 조인을 이용해서 했습니다.

     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

하지만 윈도우 기능을 이용해 한 의 선택으로 할 수 있다고 들었습니다.하지만 department_id로 그룹화해서 동시에 사용할 수는 없습니다.벌레야, 내가 바보야?

     SELECT  department_id,
     min(salary) OVER (partition by department_id)  as minsalary
     FROM employees;
     GROUP BY department_id

SQL Developer에서 00979라고 합니다.00000 - "식별 그룹화 아님"

첫 번째로 기억해야 할 것은 윈도우 기능(예:OVER()clause) 쿼리 결과에 대한 작업.즉, 서버는 먼저 쿼리를 실행한 다음 사용자가 정의한 대로 윈도우 기능을 적용합니다(물론 실제로 일어나는 일에 대한 과도한 단순화이지만 내 요점을 설명하기에는 충분합니다).

이는 실제로 동일한 쿼리에서 창 함수와 절별 그룹화를 사용할 수 있지만 캡슐화해야 한다는 것을 의미합니다.group by와 집합하는.windowed function애그리게이트, 다음과 같이:

SELECT department_id,
       min(min(salary)) OVER (partition by department_id) as minsalary
FROM employees
GROUP BY department_id;

하지만, 저는 윈도우 기능을 사용하기에는 여기가 좋지 않다는 것에 동의합니다.매트의 제안 - 제가 찬성표를 던진, 완전한 공개 - 여기서 가장 좋습니다.ROW_NUMBER()CTE또는subquery그런 다음 주에서 원하는 행만 선택합니다.SELECT).

를 사용하지 않고 두 번째 쿼리를 실행하는 경우group by당신이 이미 시도했을 수도 있는 것은 당신이 게시한 내용의 추가 세미콜론에서 - 당신은 각 직원이 부서에서 최저 임금을 표시하는 것을 볼 수 있을 것입니다.그 최소값은 분석적입니다.min()왜냐하면 창문 조항이 있기 때문입니다.PARTITION BY는 a와 동등합니다.GROUP 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 부서의 경우 직원 두 명의 급여가 동일하기 때문에 1등급입니다.

이를 인라인 뷰로 사용하여 순위가 1인 행만 선택할 수 있습니다.

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을 비교할 수 없기 때문에 해당 조인이 실패합니다.이 솔루션에는 가입이 없기 때문에 가입이 적용되지 않으며 결과에 해당 직원이 표시됩니다.

WITH cte AS (
    SELECT
       emp.*
       ,ROW_NUMBER() OVER (PARTITION BY emp.department_id ORDER BY emp.salary) as RowNumber
    FROM
       employees emp
)

SELECT c.*
FROM
    cte c
WHERE
    c.RowNumber = 1

사용할 수 있습니다.ROW_NUMBER()위와 같이 부서별 최저 급여 1열을 받는 것.을 타의경모우행든을다면으로 RANK()

그렇지 않으면 다음과 같이 할 수 있습니다.MIN() OVER하지만 이것은 당신에게 넥타이를 줄 것입니다.

WITH cte AS (
    SELECT
       emp.*
       ,MIN(emp.salary) OVER (PARTITION BY emp.department_id) as DeptMinSalary
    FROM
       employees emp
)

SELECT c.*
FROM
    cte c
WHERE
    c.salary = c.DeptMinSalary

공통 테이블 식 대신 파생 테이블로:

SELECT t.*
FROM
    (SELECT
       emp.*
       ,ROW_NUMBER() OVER (PARTITION BY emp.department_id ORDER BY emp.salary) as RowNumber
    FROM
       employees emp) t
WHERE
    t.RowNumber = 1

마지막으로 "창 기능이 있는 SQL 쿼리에서 그룹화할 수 있습니까?"라고 묻기 때문에 이 주제에 대한 생각이 있습니다.알렉스는 그것을 커버합니다.PARTITION BY는 Window Function 내의 하위 그룹과 같습니다.그러나 사용하기GROUP BYWindow 함수를 사용한 그룹화는 다음을 의미합니다.GROUP BY결과 세트는 Window Function을 평가하기 전에 평가됩니다.

, 한 윈도우 기능을 시킵니다. 단순한 원인이 됩니다.group by효과가 있을 것입니다.

그리고 오류는 정확합니다. 윈도우 함수는 집계 함수가 아니기 때문입니다.그리고 창 함수는 그룹별 멤버가 될 수 없습니다.

대신 "distent"를 사용할 수 있습니다.

SELECT DISTINCT department_id,
     min(salary) OVER (partition by department_id)  as minsalary
FROM employees;

물론 특별한 경우에는 이 모든 것이 오버사이즈입니다.하지만 저는 이해가 게임의 이름이라고 생각합니다.

SELECT t.employee_id, t.department_id, t.last_name, t.salary 
FROM (SELECT employee_id, department_id, last_name, salary, 
             MIN(salary) OVER(PARTITION BY department_id) AS dept_min_salary 
      FROM employees) t
WHERE t.salary = t.dept_min_salary;

창 함수는 집계 함수가 아니므로 department_id, 그룹 내 급여 등 집계되지 않은 레이블을 배치해야 합니다.질문을 보니, 창 기능을 사용하는 것이 제안되지 않았습니다.

SELECT  department_id,
     min(salary) OVER (partition by department_id)  as minsalary
     FROM employees;
     GROUP BY department_id, salary;

언급URL : https://stackoverflow.com/questions/40594466/can-i-group-by-in-sql-query-with-window-function

반응형