윈도우 기능이 있는 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
'programing' 카테고리의 다른 글
| jdiv 태그 내부에 이미지 추가 쿼리 (0) | 2023.08.06 |
|---|---|
| docker-compose.yml에서 명명된 볼륨의 호스트 경로를 설정하는 방법 (0) | 2023.08.06 |
| 테이블스페이스 생성 및 삭제 Oracle (0) | 2023.08.06 |
| 마시멜로의 스토리지 사용 권한 오류 (0) | 2023.08.06 |
| Android Room - 자동 생성으로 삽입된 새 행의 ID 가져오기 (0) | 2023.08.06 |