SQL有条件的展望

问题描述

我想编写一个查询,该查询标识满足条件的有序集合中的“下一个”值。 LEAD / LAG解析函数在这里似乎不适用,因为要向前看的行数根据条件是可变的(不固定)。下面的示例显示了来自示例表(tbl)的所需结果(列gnme),但是解决方案似乎并不理想。希望这里的某人可能对这种问题有更优雅的解决方案。预先感谢。

请注意,在本示例中,第1-3行如何标识第4行中的nme 迈克,第6-7行如何标识nme michael 在第8行中。

create table tbl (
  id number,nme varchar(255)
)
;

insert into tbl (id,nme) values (1,'unknown');
insert into tbl (id,nme) values (2,nme) values (3,nme) values (4,'mike');
insert into tbl (id,nme) values (5,nme) values (6,nme) values (7,nme) values (8,'michael');
insert into tbl (id,nme) values (9,nme) values (10,nme) values (11,'unknown');
 
select
  id,nme,CASE WHEN nme = 'unknown' THEN 
          NVL
          (
           (SELECT b.nme 
            FROM tbl b 
            WHERE 
              b.nme <> 'unknown'
              AND a.id < b.id 
            ORDER BY id 
            OFFSET 0 ROWS FETCH NEXT 1 ROW ONLY
           ),nme
          ) 
        ELSE nme 
        END AS gnme
FROM
  tbl a
;

+----+---------+---------+
| id | nme     | gnme    |
+----+---------+---------+
| 1  | unknown | mike    |
+----+---------+---------+
| 2  | unknown | mike    |
+----+---------+---------+
| 3  | unknown | mike    |
+----+---------+---------+
| 4  | mike    | mike    |
+----+---------+---------+
| 5  | mike    | mike    |
+----+---------+---------+
| 6  | unknown | michael |
+----+---------+---------+
| 7  | unknown | michael |
+----+---------+---------+
| 8  | michael | michael |
+----+---------+---------+
| 9  | michael | michael |
+----+---------+---------+
| 10 | michael | michael |
+----+---------+---------+
| 11 | unknown | unknown |
+----+---------+---------+

解决方法

当名称未知时,您需要下一个非未知名称。

Oracle是少数支持窗口功能ignore nullslead()的{​​{1}}选项的数据库之一。这是一项强大的功能,在您的用例中很方便:

lag()

select id,nme,case when nme = 'unknown' then lead(nullif(nme,'unknown') ignore nulls,1,'unknown') over(order by id) else nme end gnme from tbl 中的case表达式将值lead()变为'unknow',然后该函数带来下一个非null值(如果存在,则默认为unknown没有可用。)

,

您可以使用first_value分析函数:

select
  id,nvl(
        first_value(nullif(nme,'unknown') ignore nulls)over(order by id ROWS between current row and unbounded following),'unknown')
        AS gnme
FROM
  tbl a
;

完整示例进行比较:

select
  id,CASE WHEN nme = 'unknown' THEN 
          NVL
          (
           (SELECT b.nme 
            FROM tbl b 
            WHERE 
              b.nme <> 'unknown'
              AND a.id < b.id 
            ORDER BY id 
            OFFSET 0 ROWS FETCH NEXT 1 ROW ONLY
           ),nme
          ) 
        ELSE nme 
        END AS gnme,'unknown')
        AS gnme_2
FROM
  tbl a
;

结果:

        ID NME        GNME       GNME_2
---------- ---------- ---------- ----------
         1 unknown    mike       mike
         2 unknown    mike       mike
         3 unknown    mike       mike
         4 mike       mike       mike
         5 mike       mike       mike
         6 unknown    michael    michael
         7 unknown    michael    michael
         8 michael    michael    michael
         9 michael    michael    michael
        10 michael    michael    michael
        11 unknown    unknown    unknown

11 rows selected.
,

您也可以只将LAST_VALUE()与IGNORE NULL一起使用:

WITH
-- your input
tbl(id,nme) AS (
          SELECT 1,'unknown'
UNION ALL SELECT 2,'unknown'
UNION ALL SELECT 3,'unknown'
UNION ALL SELECT 4,'mike'
UNION ALL SELECT 5,'mike'
UNION ALL SELECT 6,'unknown'
UNION ALL SELECT 7,'unknown'
UNION ALL SELECT 8,'michael'
UNION ALL SELECT 9,'michael'
UNION ALL SELECT 10,'michael'
UNION ALL SELECT 11,'unknown'
)
SELECT
  *,NVL(
    LAST_VALUE(NULLIF(nme,'unknown') IGNORE NULLS) OVER(
      ORDER BY id DESC
    ),'unknown'
  ) AS gnme
FROM tbl
ORDER BY id;
-- out  id |   nme   |  gnme   
-- out ----+---------+---------
-- out   1 | unknown | mike
-- out   2 | unknown | mike
-- out   3 | unknown | mike
-- out   4 | mike    | mike
-- out   5 | mike    | mike
-- out   6 | unknown | michael
-- out   7 | unknown | michael
-- out   8 | michael | michael
-- out   9 | michael | michael
-- out  10 | michael | michael
-- out  11 | unknown | unknown

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...