zoukankan      html  css  js  c++  java
  • X 开窗函数应用 first_value ,last_value ,lead,lag ,ignore nulls ,nulls last

    oracle通过分析函数获取当前行之前的不为空的值
    使用last_value,但是要注明ignore nulls 
    比如有数据如下:
    RN      ADDRESS     ARRIVAL_TIME         USERID    
     ------  ----------  -------------------  --------- 
     1       A1          2012-7-9 下午12:03:21  1         
     (null)  A2          2012-7-9 下午12:04:21  2         
     (null)  A3          2012-7-9 下午12:05:21  3         
     2       A1          2012-7-9 下午12:08:21  4         
     (null)  A2          2012-7-9 下午12:09:21  5         
     (null)  A3          2012-7-9 下午12:10:21  6         
     3       A1          2012-7-9 下午12:13:21  7         
     (null)  A3          2012-7-9 下午12:15:21  8         
     4       A1          2012-7-9 下午12:18:23  9         
     5       A1          2012-7-9 下午12:19:21  10        
     (null)  A2          2012-7-9 下午12:20:21  11        
     (null)  A3          2012-7-9 下午12:21:21  12        
     6       A1          2012-7-9 下午12:23:23  13        
     (null)  A2          2012-7-9 下午12:24:21  14 
     
     select rn,address,arrival_time,userid,last_value(rn ignore nulls) over(order by userid) from test
     查询结果如下:
      RN      ADDRESS     ARRIVAL_TIME         USERID     GROUP_T    
     ------  ----------  -------------------  ---------  ---------- 
     1       A1          2012-7-9 下午12:03:21  1          1          
     (null)  A2          2012-7-9 下午12:04:21  2          1          
     (null)  A3          2012-7-9 下午12:05:21  3          1          
     2       A1          2012-7-9 下午12:08:21  4          2          
     (null)  A2          2012-7-9 下午12:09:21  5          2          
     (null)  A3          2012-7-9 下午12:10:21  6          2          
     3       A1          2012-7-9 下午12:13:21  7          3          
     (null)  A3          2012-7-9 下午12:15:21  8          3          
     4       A1          2012-7-9 下午12:18:23  9          4          
     5       A1          2012-7-9 下午12:19:21  10         5          
     (null)  A2          2012-7-9 下午12:20:21  11         5          
     (null)  A3          2012-7-9 下午12:21:21  12         5          
     6       A1          2012-7-9 下午12:23:23  13         6          
     (null)  A2          2012-7-9 下午12:24:21  14         6 
    除了last_value(rn ignore nulls),到了11g r2,oracle还支持了lag(rn ignore nulls)和lead(rn ignore nulls)

    需求,取最新的数据行,但是如果最新的数据行某列中没有数据,那么取次新行某列中的数据:

    案例一:

    SQL> 
    SQL> select * from tab_1;
    
            ID COL2                 COL_TIME    SHUJU_ID
    ---------- -------------------- --------- ----------
             1 tijian               02-MAR-21         75
             2 xunjian              02-MAR-21         75
             3 chaxun               02-MAR-21         75
               dba                  02-MAR-21         75
               abc                  02-MAR-21         75
             4 def                  03-MAR-21         75
    
    6 rows selected.
               
               
    
    SQL> select t.*,
           to_char(col_time,'yyyy-mm-dd hh24:mi:ss') time_,
           id,
           coalesce(id,lead(id ignore nulls) over(partition by shuju_id order by col_time desc)) as shiji_id,     ---coalesce,lead 配合 ignore nulls 
           row_number() over(partition by shuju_id order by col_time desc) as rn
      from tab_1 t;   
    
    
    
            ID COL2                 COL_TIME    SHUJU_ID TIME_                       ID   SHIJI_ID         RN
    ---------- -------------------- --------- ---------- ------------------- ---------- ---------- ----------
             4 def                  03-MAR-21         75 2021-03-03 05:46:21          4          4          1    ----此条数据满足
               abc                  02-MAR-21         75 2021-03-02 14:50:25                     3          2
               dba                  02-MAR-21         75 2021-03-02 14:43:37                     3          3
             3 chaxun               02-MAR-21         75 2021-03-02 14:43:20          3          3          4
             2 xunjian              02-MAR-21         75 2021-03-02 14:43:05          2          2          5
             1 tijian               02-MAR-21         75 2021-03-02 14:42:49          1          1          6
    
    6 rows selected.

    方法二:

    SQL> select t.*,
           to_char(col_time,'yyyy-mm-dd hh24:mi:ss') time_,
           id id_o,
           last_value(id ignore nulls)over(partition by shuju_id order by col_time ) as shiji_id_1,   --用 last_value的方法写
           lead(id ignore nulls) over(partition by shuju_id order by col_time desc) as shiji_id_2,    --用 lead的方法写
           row_number() over(partition by shuju_id order by col_time desc) as rn
      from tab_1 t ;
    
            ID COL2                 COL_TIME    SHUJU_ID TIME_                     ID_O SHIJI_ID_1 SHIJI_ID_2         RN
    ---------- -------------------- --------- ---------- ------------------- ---------- ---------- ---------- ----------
             1 tijian               02-MAR-21         75 2021-03-02 14:42:49          1          1                     5
             2 xunjian              02-MAR-21         75 2021-03-02 14:43:05          2          2          1          4
             3 chaxun               02-MAR-21         75 2021-03-02 14:43:20          3          3          2          3
               dba                  02-MAR-21         75 2021-03-02 14:43:37                     3          3          2
               abc                  02-MAR-21         75 2021-03-02 14:50:25                     3          3          1
    
    SQL> 
    LAG 窗口函数 说明:
    
    
    
    LAG 窗口函数返回位于分区中当前行的上方(之前)的某个给定偏移量位置的行的值。
    
    Syntax
    
    LAG (value_expr [, offset ])
    [ IGNORE NULLS | RESPECT NULLS ]
    OVER ( [ PARTITION BY window_partition ] ORDER BY window_ordering )
    Arguments
    value_expr
    对其执行函数的目标列或表达式。
    
    offset
    一个可选参数,该参数指定要返回其值的当前行前面的行数。偏移量可以是常量整数或计算结果为整数的表达式。如果您未指定偏移量,则 Amazon Redshift 使用 1 作为默认值。偏移量为 0 表示当前行。
    
    IGNORE NULLS
    一个可选规范,该规范指示 Amazon Redshift 应跳过 null 值以确定要使用的行。如果未列出 IGNORE NULLS,则包含 Null 值。
    
    注意
    您可以使用 NVL 或 COALESCE 表达式将 null 值替换为另一个值。有关更多信息,请参阅NVL 表达式.
    
    RESPECT NULLS
    指示 Amazon Redshift 应包含 null 值以确定要使用的行。如果您未指定 IGNORE NULLS,则默认情况下不支持 RESPECT NULLS。
    
    OVER
    指定窗口分区和排序。OVER 子句不能包含窗口框架规范。
    
    PARTITION BY window_partition
    一个可选参数,该参数设置 OVER 子句中每个组的记录范围。
    
    ORDER BY window_ordering
    对每个分区中的行进行排序。
    
    LAG 窗口函数支持使用任何 Amazon Redshift 数据类型的表达式。返回类型与 value_expr. 的类型相同。
    
    
    
    
    Examples
    以下示例显示已售给买家 ID 为 3 的买家的票数以及买家 3 的购票时间。要将每个销售与买家 3 的上一销售进行比较,查询要返回每个销售的上一销量。
    由于 1/16/2008 之前未进行购买,则第一个上一销量值为 nullselect buyerid, saletime, qtysold,
    lag(qtysold,1) over (order by buyerid, saletime) as prev_qtysold
    from sales where buyerid = 3 order by buyerid, saletime;
    
    buyerid |      saletime       | qtysold | prev_qtysold
    ---------+---------------------+---------+--------------
    3 | 2008-01-16 01:06:09 |       1 |
    3 | 2008-01-28 02:10:01 |       1 |            1
    3 | 2008-03-12 10:39:53 |       1 |            1
    3 | 2008-03-13 02:56:07 |       1 |            1
    3 | 2008-03-29 08:21:39 |       2 |            1
    3 | 2008-04-27 02:39:01 |       1 |            2
    3 | 2008-08-16 07:04:37 |       2 |            1
    3 | 2008-08-22 11:45:26 |       2 |            2
    3 | 2008-09-12 09:11:25 |       1 |            2
    3 | 2008-10-01 06:22:37 |       1 |            1
    3 | 2008-10-20 01:55:51 |       2 |            1
    3 | 2008-10-28 01:30:40 |       1 |            2
    (12 rows)

    错误案例  first_value :

    SQL> select * from tab_1;
    
            ID COL2                 COL_TIME    SHUJU_ID
    ---------- -------------------- --------- ----------
             1 tijian               02-MAR-21         75
             2 xunjian              02-MAR-21         75
             3 chaxun               02-MAR-21         75
               dba                  02-MAR-21         75
               abc                  02-MAR-21         75
             4 def                  03-MAR-21         75
               efg                  03-MAR-21         75
               111                  26-FEB-21         75
    
    8 rows selected.
    
    
    
    SQL> select t.*,
           to_char(col_time,'yyyy-mm-dd hh24:mi:ss') time_,
           id id_o,
           last_value(id ignore nulls)over(partition by shuju_id order by col_time ) as shiji_id_1,
           coalesce(id,lead(id ignore nulls) over(partition by shuju_id order by  col_time desc)) as shiji_id_2,
           first_value(id )over(partition by shuju_id order by col_time desc) as shiji_id_31,
           first_value(id ignore nulls)over(partition by shuju_id order by col_time desc) as shiji_id_32,
           row_number() over(partition by shuju_id order by col_time desc) as rn
      from tab_1 t   ;
    
            ID COL2                 COL_TIME    SHUJU_ID TIME_                     ID_O SHIJI_ID_1 SHIJI_ID_2 SHIJI_ID_31 SHIJI_ID_32         RN
    ---------- -------------------- --------- ---------- ------------------- ---------- ---------- ----------  ----------  ---------- ----------
               111                  26-FEB-21         75 2021-02-26 05:59:47                                                      4          8
             1 tijian               02-MAR-21         75 2021-03-02 14:42:49          1          1          1                     4          7
             2 xunjian              02-MAR-21         75 2021-03-02 14:43:05          2          2          2                     4          6
             3 chaxun               02-MAR-21         75 2021-03-02 14:43:20          3          3          3                     4          5
               dba                  02-MAR-21         75 2021-03-02 14:43:37                     3          3                     4          4
               abc                  02-MAR-21         75 2021-03-02 14:50:25                     3          3                     4          3
             4 def                  03-MAR-21         75 2021-03-03 05:46:21          4          4          4                     4          2
               efg                  03-MAR-21         75 2021-03-03 05:52:53                     4          4                                1
    
    8 rows selected.
    
    这个问题不能用 first_value 来解决,因为 对于 null 值在排序中默认是最大值,排在最后面,如果用倒序的话就排在最上面。
    这里如果用first_value 那么对应的每行都取第一个值,那么都是null值,即使用
    ignore nulls 那么返回的也是null值。
    
    
    ignore nulls 表示排除null值,但是所有值都是null,那么只能返回null
  • 相关阅读:
    开通博客第一天
    Vue 打包配置productionSourceMap 的记录
    supervisorctl 的 简单记录
    mvn打包方式记录
    springboot日志配置,关于logback
    springboot集成swagger
    关于mapper文件的bean
    elasticsearch 连接、操作记录
    关于前后端分离文件上传的些许问题
    代码优化--策略模式的四种表现
  • 原文地址:https://www.cnblogs.com/chendian0/p/14469265.html
Copyright © 2011-2022 走看看