SQL进阶技巧:如何进行行值轮转?

01

 

需求描述

 

你想返回每个员工的姓名、工资,以及下一个比当前员工高和低的工资值。如果没有找到更高或更低的工资值,你希望结果集可以“折回”(第一个 SAL 的前一行是最后一个 SAL;反之,最后一个 SAL 的下一行即是第一个 SAL)。你希望返回如下所示的结果集。

 

其实就是寻找比当前员工工资低及工资高的前后的工资值,如果遇到最高的工资或最低的工资则进行折回

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
ENAME             SAL    FORWARD     REWIND---------- ---------- ---------- ----------SMITH             800        950       5000JAMES             950       1100        800ADAMS            1100       1250        950WARD             1250       1250       1100MARTIN           1250       1300       1250MILLER           1300       1500       1250TURNER           1500       1600       1300ALLEN            1600       2450       1500CLARK            2450       2850       1600BLAKE            2850       2975       2450JONES            2975       3000       2850SCOTT            3000       3000       2975FORD             3000       5000       3000KING             5000        800       3000

 

 

 

02

 

问题分析

 

窗口函数 LAG OVER 和 LEAD OVER 将分别返回当前行的上一行和下一行记录。“上一行”或“下一行”取决于 OVER 子句里的 ORDER BY 部分。我们首先按照 SAL 排序数据集,并提取出了当前行的上一行和下一行。

 

  •  
  •  
  •  
  •  
select ename,sal,       lead(sal,1)over(order by sal) forward,       lag(sal,1)over(order by sal) rewind  from emp
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
ENAME             SAL    FORWARD     REWIND---------- ---------- ---------- ----------SMITH             800        950JAMES             950       1100        800ADAMS            1100       1250        950WARD             1250       1250       1100MARTIN           1250       1300       1250MILLER           1300       1500       1250TURNER           1500       1600       1300ALLEN            1600       2450       1500CLARK            2450       2850       1600BLAKE            2850       2975       2450JONES            2975       3000       2850SCOTT            3000       3000       2975FORD             3000       5000       3000KING             5000                  3000

注意,员工 SMITH 的 REWIND 是 Null,而 KING 的 FORWARD 也是 Null;这是因为两个人的 SAL 分别是最低值和最高值。“问题”部分提到,FORWARD 或 REWIND 若出现 Null 值,则应该“折回”。这就意味着,对于最大的 SAL,FORWARD 值应为 表中最小的 SAL;而对于最小的 SAL,REWIND 值应为最大的 SAL。没有指定分区(即 OVER 子句后面跟一对空括号)的窗口函数 MIN OVER 和 MAX OVER 将分别返回最大和最小的 SAL。结果集如下所示。 

  •  
  •  
  •  
  •  
select ename,sal,       nvl(lead(sal,1)over(order by sal),min(sal)over()) forward,       nvl(lag(sal,1)over(order by sal),max(sal)over()) rewindfrom emp

注意这里面 "折回",采用了NVL()函数【NUL值转换函数】,NVL(X,Y)函数可以将第一个位置处X字段中的NULL值转换为第二个位置Y处制定的值。

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
ENAME             SAL    FORWARD     REWIND---------- ---------- ---------- ----------SMITH             800        950       5000JAMES             950       1100        800ADAMS            1100       1250        950WARD             1250       1250       1100MARTIN           1250       1300       1250MILLER           1300       1500       1250TURNER           1500       1600       1300ALLEN            1600       2450       1500CLARK            2450       2850       1600BLAKE            2850       2975       2450JONES            2975       3000       2850SCOTT            3000       3000       2975FORD             3000       5000       3000KING             5000       800        3000

 

03

小结

本文分析了一种行值进行轮转的技巧,主要使用lag(),lead()函数及NVL函数进行解决。

 

posted @ 2024-10-23 10:53  CharyGao  阅读(0)  评论(0编辑  收藏  举报