在解析表达式中访问 "outer row" 值

Access "outer row" value in an analytic expression

我想访问我在其上编写分析表达式的“当前行”的值。例如,给定以下样本数据:

DROP TABLE emp PURGE;

CREATE TABLE emp (
  empno    NUMBER(4) CONSTRAINT pk_emp PRIMARY KEY,
  ename    VARCHAR2(10),
  job      VARCHAR2(9),
  mgr      NUMBER(4),
  hiredate DATE,
  sal      NUMBER(7,2),
  comm     NUMBER(7,2),
  deptno   NUMBER(2)
);

INSERT INTO emp VALUES (7369,'SMITH','CLERK',7902,to_date('17-12-1980','dd-mm-yyyy'),800,NULL,20);
INSERT INTO emp VALUES (7499,'ALLEN','SALESMAN',7698,to_date('20-2-1981','dd-mm-yyyy'),1600,300,30);
INSERT INTO emp VALUES (7521,'WARD','SALESMAN',7698,to_date('22-2-1981','dd-mm-yyyy'),1250,500,30);
INSERT INTO emp VALUES (7566,'JONES','MANAGER',7839,to_date('2-4-1981','dd-mm-yyyy'),2975,NULL,20);
INSERT INTO emp VALUES (7654,'MARTIN','SALESMAN',7698,to_date('28-9-1981','dd-mm-yyyy'),1250,1400,30);
INSERT INTO emp VALUES (7698,'BLAKE','MANAGER',7839,to_date('1-5-1981','dd-mm-yyyy'),2850,NULL,30);
INSERT INTO emp VALUES (7782,'CLARK','MANAGER',7839,to_date('9-6-1981','dd-mm-yyyy'),2450,NULL,10);
INSERT INTO emp VALUES (7788,'SCOTT','ANALYST',7566,to_date('13-7-87','dd-mm-rr')-85,3000,NULL,20);
INSERT INTO emp VALUES (7839,'KING','PRESIDENT',NULL,to_date('17-11-1981','dd-mm-yyyy'),5000,NULL,10);
INSERT INTO emp VALUES (7844,'TURNER','SALESMAN',7698,to_date('8-9-1981','dd-mm-yyyy'),1500,0,30);
INSERT INTO emp VALUES (7876,'ADAMS','CLERK',7788,to_date('13-7-87', 'dd-mm-rr')-51,1100,NULL,20);
INSERT INTO emp VALUES (7900,'JAMES','CLERK',7698,to_date('3-12-1981','dd-mm-yyyy'),950,NULL,30);
INSERT INTO emp VALUES (7902,'FORD','ANALYST',7566,to_date('3-12-1981','dd-mm-yyyy'),3000,NULL,20);
INSERT INTO emp VALUES (7934,'MILLER','CLERK',7782,to_date('23-1-1982','dd-mm-yyyy'),1300,NULL,10);
COMMIT;

假设我想计算平均值(使用 deptno 进行分区)仅当薪水小于“外行”的薪水值时

这是计算特定 window 中每个人的平均值的查询,注释掉我希望能够执行的操作的行,“伪代码”。

SELECT t.empno, t.deptno, t.sal
  ,AVG(t.sal) OVER (PARTITION BY t.deptno) AS avg_dept_sal
  --,AVG(CASE WHEN t.sal < OUTER_VALUE(t.sal) THEN t.sal ELSE NULL END) OVER (PARTITION BY t.deptno) AS avg_dept_sal_2
  FROM emp t
;

因此,虽然 avg_dept_sal returns ~2916 对于 deptno = 10,对于每一行,avg_dept_sal_2 应该 return:

实现此目标的最佳方法是什么?

在解析函数中使用RANGEwindow:

SELECT empno,
       deptno,
       sal,
       AVG(sal) OVER (PARTITION BY deptno) AS avg_dept_sal,
       AVG(sal) OVER (
         PARTITION BY deptno
         ORDER BY sal
         RANGE BETWEEN UNBOUNDED PRECEDING AND 0.01 PRECEDING
       ) AS avg_dept_sal_2
FROM   emp;

其中,对于示例数据,输出:

EMPNO DEPTNO SAL AVG_DEPT_SAL AVG_DEPT_SAL_2
7934 10 1300 2916.666666666666666666666666666666666667 null
7782 10 2450 2916.666666666666666666666666666666666667 1300
7839 10 5000 2916.666666666666666666666666666666666667 1875
7369 20 800 2175 null
7876 20 1100 2175 800
7566 20 2975 2175 950
7788 20 3000 2175 1625
7902 20 3000 2175 1625
7900 30 950 1566.666666666666666666666666666666666667 null
7654 30 1250 1566.666666666666666666666666666666666667 950
7521 30 1250 1566.666666666666666666666666666666666667 950
7844 30 1500 1566.666666666666666666666666666666666667 1150
7499 30 1600 1566.666666666666666666666666666666666667 1237.5
7698 30 2850 1566.666666666666666666666666666666666667 1310

db<>fiddle here