복붙노트

[SQL] 와 BY와 오라클의 KEEP없이 PARTITION

SQL

와 BY와 오라클의 KEEP없이 PARTITION

파티션에 집계 함수를 적용 : 나는 같은 결과를 갖고있는 것 같아요 두 개의 질의를 가로 질러왔다.

이 두 개의 쿼리 사이에 어떤 차이가 있는지 궁금 오전 :

SELECT empno,
   deptno,
   sal,
   MIN(sal) OVER (PARTITION BY deptno) "Lowest",
   MAX(sal) OVER (PARTITION BY deptno) "Highest"
FROM empl

SELECT empno,
   deptno,
   sal,
   MIN(sal) KEEP (DENSE_RANK FIRST ORDER BY sal) OVER (PARTITION BY deptno) "Lowest",
   MAX(sal) KEEP (DENSE_RANK LAST ORDER BY sal) OVER (PARTITION BY deptno) "Highest"
FROM empl

첫 번째 버전은 더 논리적이다하지만, 두 번째는 어떤 특별한 경우에, 어쩌면 약간의 성능을 최적화 할 수있다.

해결법

  1. ==============================

    1.당신의 집계는 당신이 정렬되는 것과 같은 열 때문에 당신의 예에서 차이가 없습니다. 당신이 다른 열에 종류의 집계 때 'KEEP'의 진정한 포인트 / 전원입니다. 예를 들어 (다른 답변에서 "테스트"테이블을 차입) ...

    당신의 집계는 당신이 정렬되는 것과 같은 열 때문에 당신의 예에서 차이가 없습니다. 당신이 다른 열에 종류의 집계 때 'KEEP'의 진정한 포인트 / 전원입니다. 예를 들어 (다른 답변에서 "테스트"테이블을 차입) ...

    SELECT deptno,  min(name) keep ( dense_rank first order by sal desc, name  ) ,
    max(sal)
    FROM test
    group by deptno
    

    ;

    이 쿼리는 각 부서에서 가장 높은 급여를 가진 사람의 이름을 가져옵니다. 는 "KEEP"절없이 대안을 고려 :

    SELECT deptno, name, sal
    FROM test t
    WHERE not exists ( SELECT 'person with higher salary in same department'
                                                FROM test t2  
                                                WHERE t2.deptno = t.deptno
                                                and ((  t2.sal > t.sal )
                                                OR ( t2.sal = t.sal AND t2.name < t.name ) ) )
    

    킵 절보다 쉽고 효율적이다 ((34)는이 간단한 예에서 대안을 얻는다 대 단 3 일치 가져).

  2. ==============================

    2.

    MIN(sal) KEEP (DENSE_RANK FIRST ORDER BY sal) OVER (PARTITION BY deptno)
    

    명령문은 (대략) 오른쪽에서 왼쪽 순서로 고려 될 수있다 :

    이 경우 MIN 및 DENSE_RANK FIRST는 SAL 컬럼에 모두 운영 그렇게 같은 일을하고 KEEP (DENSE_RANK FIRST ORDER BY의 샐를) 할 것입니다 중복입니다.

    당신은 최소 다른 열을 사용하지만 경우에 당신은 효과를 볼 수 있습니다

    SQL 바이올린

    오라클 11g R2 스키마 설정 :

    CREATE TABLE test (name, sal, deptno) AS
    SELECT 'a', 1, 1 FROM DUAL
    UNION ALL SELECT 'b', 1, 1 FROM DUAL
    UNION ALL SELECT 'c', 1, 1 FROM DUAL
    UNION ALL SELECT 'd', 2, 1 FROM DUAL
    UNION ALL SELECT 'e', 3, 1 FROM DUAL
    UNION ALL SELECT 'f', 3, 1 FROM DUAL
    UNION ALL SELECT 'g', 4, 2 FROM DUAL
    UNION ALL SELECT 'h', 4, 2 FROM DUAL
    UNION ALL SELECT 'i', 5, 2 FROM DUAL
    UNION ALL SELECT 'j', 5, 2 FROM DUAL;
    

    쿼리 1 :

    SELECT DISTINCT
      MIN(sal) KEEP (DENSE_RANK FIRST ORDER BY sal) OVER (PARTITION BY deptno) AS min_sal_first_sal,
      MAX(sal) KEEP (DENSE_RANK FIRST ORDER BY sal) OVER (PARTITION BY deptno) AS max_sal_first_sal,
      MIN(name) KEEP (DENSE_RANK FIRST ORDER BY sal) OVER (PARTITION BY deptno) AS min_name_first_sal,
      MAX(name) KEEP (DENSE_RANK FIRST ORDER BY sal) OVER (PARTITION BY deptno) AS max_name_first_sal,
      MIN(name) KEEP (DENSE_RANK LAST ORDER BY sal) OVER (PARTITION BY deptno) AS min_name_last_sal,
      MAX(name) KEEP (DENSE_RANK LAST ORDER BY sal) OVER (PARTITION BY deptno) AS max_name_last_sal,
      deptno
    FROM test
    

    결과 :

    | MIN_SAL_FIRST_SAL | MAX_SAL_FIRST_SAL | MIN_NAME_FIRST_SAL | MAX_NAME_FIRST_SAL | MIN_NAME_LAST_SAL | MAX_NAME_LAST_SAL | DEPTNO |
    |-------------------|-------------------|--------------------|--------------------|-------------------|-------------------|--------|
    |                 1 |                 1 |                  a |                  c |                 e |                 f |      1 |
    |                 4 |                 4 |                  g |                  h |                 i |                 j |      2 |
    
  3. ==============================

    3.MT0의 대답 @에서 언급 한 차이를 자세히 설명합니다 : 첫 번째 쿼리에서 집계 함수 MIN과 MAX는 일을하고있다 제 중에 실제 행은 FIRST, LAST 및 KEEP 의해 촬상되고있다.

    MT0의 대답 @에서 언급 한 차이를 자세히 설명합니다 : 첫 번째 쿼리에서 집계 함수 MIN과 MAX는 일을하고있다 제 중에 실제 행은 FIRST, LAST 및 KEEP 의해 촬상되고있다.

    당신은 두 번째 예에서는 MIN과 MAX를 대체 할 수 있으며 여전히 정답 (가장 높은 급여를) 제공합니다.

    더 많은 정보를 위해 다음 문서를 참조하십시오.

  4. ==============================

    4.두 열의으로 주문 및 중 하나 또는 둘 모두 그 열을 가져 오는 경우 그것은 또한 도움이 될 수 있습니다.

    두 열의으로 주문 및 중 하나 또는 둘 모두 그 열을 가져 오는 경우 그것은 또한 도움이 될 수 있습니다.

    CREATE TABLE test (name, sal, deptno) AS
    SELECT 'adam', 100, 1 FROM DUAL
    UNION ALL SELECT 'bravo', 500, 1 FROM DUAL
    UNION ALL SELECT 'coy', 456, 1 FROM DUAL
    UNION ALL SELECT 'david', 50, 1 FROM DUAL
    UNION ALL SELECT 'ethan', 50, 1 FROM DUAL
    UNION ALL SELECT 'feral', 300, 1 FROM DUAL;
    

    이제 두 직원이 같은 최저 임금이있는 경우 이름이 첫 번째 알파벳 오는 하나를 가져되어 가장 낮은 급여와 직원뿐만 아니라 person.Condition의 급여를 선택합니다.

      select o.deptno
    ,min(o.sal) keep 
      (dense_rank first order by o.sal, o.name) least_salary
    ,min(o.name) keep 
      (dense_rank first order by o.sal, o.name) least_salary_person
     from test o
      group by 
     o.deptno;
    

    산출:

    DEPTNO  LEAST_SALARY    LEAST_SALARY_PERSON
    1        50             david
    
  5. ==============================

    5.이 쿼리는 각 부서에서 가장 높은 급여를 가진 사람의 이름을 가져옵니다.

    이 쿼리는 각 부서에서 가장 높은 급여를 가진 사람의 이름을 가져옵니다.

    select MIN(ename),sal,deptno
    from emp where sal in
       (
        select max(sal) from emp group by deptno
       )
    GROUP BY sal,deptno;
    
  6. from https://stackoverflow.com/questions/20145952/partition-by-with-and-without-keep-in-oracle by cc-by-sa and MIT license