oracle sql运行总范围

时间:2019-04-10 08:28:33

标签: sql oracle oracle11g

我有两个表tab_a作为

[
  {
    "name": "spt_fallback_db",
    "object_id": 117575457,
    "principal_id": null,
    "schema_id": 1,
    "parent_object_id": 0,
    "type": "U ",
    "type_desc": "USER_TABLE",
    "create_date": "2003-04-08T09:18:01.557",
    "modify_date": "2017-08-22T19:40:40.763",
    "is_ms_shipped": true,
    "is_published": false,
    "is_schema_published": false,
    "lob_data_space_id": 0,
    "filestream_data_space_id": null,
    "max_column_id_used": 8,
  ... etc

2个表的tab_b为

   SUB_ID AMOUNT
    1     10
    2     5
    3     7
    4     15
    5     4

slab_start将始终比上一个slab_end的slab_end多

如果运行tab_a的运行总计,则结果为

    slab_number slab_start slab_end 
    1             12          20
    2             21          25
    3             26          35

我需要进行SQL查询,以检查run_sum小于第一个slab_number时,哪个slab_NUMBER应该为零;如果run_sum大于最后一个slab_number,则为空白,但超出限制的行除外。 预期结果是

 select sub_id , sum(amount)  OVER(ORDER BY sub_id) run_sum
from tab_a

sub_id run_sum
  1     10
  2     15
  3     22
  4     37
  5     41

我已经尝试过了。

首先找到超出限制i的运行总和。最后一个slab_end

  sub_id run_sum slab_number
      1     10    0
      2     15    1
      3     22    2
      4     37    3
      5     41    NULL

然后在下面的查询中使用

        select min(  run_sum ) 
              from  (select sub_id , sum(amount)  OVER(ORDER BY sub_id) run_sum
from tab_a ) where run_sum>=35

还有其他改进方法吗?

3 个答案:

答案 0 :(得分:0)

您可以尝试以下方法:

select a.sub_id , sum(a.amount)  OVER(ORDER BY a.sub_id) run_sum
 ,case when b.slab_number=1 then 0 else  lag(b.slab_number,1) over (order by a.sub_id)end slab_number
from tab_a a
left join tab_b b on a.SUB_ID = b.slab_number

答案 1 :(得分:0)

有些奇怪的要求:)使用一些解析函数和case whenRow_number,当您需要 first max() over()sum() over(),当您需要从多行中获取信息时:

with  
  a as (
    select sub_id, row_number() over (order by sub_id) rn, 
           sum(amount) over (order by sub_id) rs 
      from tab_a),
  b as (select tab_b.*, max(slab_number) over () msn from tab_b )
select sub_id, rs, 
       case when sn is null and row_number() over (partition by sn order by sub_id) = 1 
            then msn else sn 
       end sn
  from (
    select sub_id, rs, max(msn) over () msn,
           case when slab_number is null and rn = 1 then 0 else slab_number end sn
      from a left join b on rs between slab_start and slab_end)

dbfiddle demo

答案 2 :(得分:0)

我认为这基本上是一个带有默认值的left join

select a.*,
       (case when a.run_sum < bb.min_slab_num then 0
             else b.slab_num
        end) as slab_num
from (select sub_id,
             sum(amount) over (order by sub_id) as run_sum
      from tab_a
     ) a left join
     tab_b b
     on a.run_sum between slab_start and slab_end cross join
     (select min(slab_start) as min_slab_start
      from tab_b
     ) bb;