繁体   English   中英

基于SQL上面的行计算的列值

[英]Calculated column value based on rows above SQL

我在我们的程序数据库中有这个愚蠢的表。 程序不是我们的,因此无法更改表格内容。 该表以不可读的代码存储类似 SQL 的表达式。 我正在将这些值转换回 SQL 表达式以运行这些表达式。 到目前为止,翻译部分进行得很顺利。 到目前为止的结果是一个如下表:

+--------+--------+---------+----------------+-----------------+
| CODE   | SEQNUM | LOGICAL | EXPRESSION     | EXPRESSIONVALUE |
+--------+--------+---------+----------------+-----------------+
| A23000 | 1      | NULL    | OTHERCODE LIKE | 'A522%'         |
+--------+--------+---------+----------------+-----------------+
| A23000 | 2      | OR      | OTHERCODE =    | 'A62342'        |
+--------+--------+---------+----------------+-----------------+
| A23000 | 3      | OR      | OTHERCODE =    | 'A62343'        |
+--------+--------+---------+----------------+-----------------+
| B43000 | 1      | NULL    | OTHERCODE IN   | 'B34324'        |
+--------+--------+---------+----------------+-----------------+
| B43000 | 2      | NULL    | NULL           | 'B92338'        |
+--------+--------+---------+----------------+-----------------+
| B43000 | 3      | NULL    | NULL           | 'B92342'        |
+--------+--------+---------+----------------+-----------------+
| B43000 | 4      | NULL    | NULL           | 'B02349'        |
+--------+--------+---------+----------------+-----------------+
| B43000 | 5      | OR      | OTHERCODE =    | 'B32443'        |
+--------+--------+---------+----------------+-----------------+

或者为了让我拥有有效的 SQL 语句,我需要在有“in-expression”的行后面加上逗号。 我认为这需要基于较早的行。 我需要有一张像:

+--------+--------+---------+----------------+-----------------+------------+
| CODE   | SEQNUM | LOGICAL | EXPRESSION     | EXPRESSIONVALUE | CALCULETED |
+--------+--------+---------+----------------+-----------------+------------+
| A23000 | 1      | NULL    | OTHERCODE LIKE | 'A522%'         | NULL       |
+--------+--------+---------+----------------+-----------------+------------+
| A23000 | 2      | OR      | OTHERCODE =    | 'A62342'        | NULL       |
+--------+--------+---------+----------------+-----------------+------------+
| A23000 | 3      | OR      | OTHERCODE =    | 'A62343'        | NULL       |
+--------+--------+---------+----------------+-----------------+------------+
| B43000 | 1      | NULL    | OTHERCODE IN   | 'B34324'        | ','        |
+--------+--------+---------+----------------+-----------------+------------+
| B43000 | 2      | NULL    | NULL           | 'B92338'        | ','        |
+--------+--------+---------+----------------+-----------------+------------+
| B43000 | 3      | NULL    | NULL           | 'B92342'        | ','        |
+--------+--------+---------+----------------+-----------------+------------+
| B43000 | 4      | NULL    | NULL           | 'B02349'        | NULL       |
+--------+--------+---------+----------------+-----------------+------------+
| B43000 | 5      | OR      | OTHERCODE =    | 'B32443'        | NULL       |
+--------+--------+---------+----------------+-----------------+------------+

这可能与SQL有关吗?

这会有帮助吗?

SQL> with test (code, seqnum, logical, expression, value) as
  2    (select 'a23', 1, null, 'othercode like', 'a522%'  from dual union all
  3     select 'a23', 2, 'or', 'othercode ='   , 'a62342' from dual union all
  4     select 'a23', 3, 'or', 'othercode ='   , 'a62343' from dual union all
  5     --
  6     select 'b43', 1, null, 'othercode in'  , 'b34324' from dual union all
  7     select 'b43', 2, null, 'null'          , 'b92342' from dual union all
  8     select 'b43', 3, null, 'null'          , 'b02349' from dual union all
  9     select 'b43', 4, 'or', 'othercode ='   , 'b34243' from dual
 10    ),
 11  poc as
 12    -- SEQNUM where "IN" begins
 13   (select code, min(seqnum) minseq
 14    from test
 15    where expression = 'othercode in'
 16    group by code
 17    ),
 18  zav as
 19    -- SEQNUM where "IN" part ends
 20    (select t.code, max(t.seqnum) maxseq
 21     from test t join poc p on p.code = t.code
 22     where t.seqnum > p.minseq
 23       and t.expression <> 'null'
 24     group by t.code
 25    )
 26  select t.code, t.seqnum, t.logical, t.expression, t.value,
 27    case when t.seqnum >= p.minseq and t.seqnum < z.maxseq then ','
 28         else null
 29    end calc
 30  from test t left join poc p on p.code = t.code
 31              left join zav z on z.code = t.code
 32  order by code, seqnum;

COD     SEQNUM LO EXPRESSION     VALUE   C
--- ---------- -- -------------- ------- -
a23          1    othercode like a522%
a23          2 or othercode =    a62342
a23          3 or othercode =    a62343
b43          1    othercode in   b34324  ,
b43          2    null           b92342  ,
b43          3    null           b02349  ,
b43          4 or othercode =    b342443

7 rows selected.

SQL>

您可以使用分析函数执行此逻辑:

select t.*,
       (case when coalesce(expression, lag(expression ignore nulls) over (partition by code order by seqnum)) like '% in' and
                  ((lead(logical) over (partition by code order by seqnum) is null and
                    lead(seqnum) over (partition by code order by seqnum) is not null
                   ) or
                   lead(seqnum) over (partition by code order by seqnum) is not null
                  )
             then ','
        end) as calculated
from test t;

的逻辑来实现识别具有相关联的行in的逻辑-这是lag(ignore nulls)

除了最后一行之外,所有这些行都有一个逗号。 这很棘手,因为最后一行可能是表达式的结尾( code的最后一行seqnum )。 或者,可能会出现一个新的布尔表达式。

我添加了更多测试用例来证明这是有效的:

  • in之后没有表达式。
  • in列表中只有一个值。
  • in之前的另一个表达式。

是db<>小提琴。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM