PL / SQL - 如何根据表字段值运行不同的选择

时间:2017-12-08 13:51:45

标签: sql oracle case

我在PL / SLQ功能中有以下情况。 根据现有的表字段值,我可能会运行不同的选择。 特别: 对于特定的BILL CODE(PINGPONG),我可以有多行,我只需要获取SYS_FIELD值。 根据以下条件,此字段只能获取一次: 如果字段prep_seq_num = 0且primary_ind = 0,则只需直接获取此行sys_field值,并且不处理其他可能的prep_seq_num和不同于0的primary_ind值。 如果该行不存在,则从prep_seq_num!= 0和primary_ind = 1中获取sys_field值。 对于这两种情况,只能有一个实例/行。 如果我有以下BILL表情况:

Tracking_ID  BSCO_CODE_ID  PREP_SEQ_NUM  ITEM_CAT_CODE_ID PRIMARY_IND SYS_FIELD
    1            PINGPONG        61             5               1        50
    2            PINGPONG        0              1               0        100

然后我应该从sys_field中获取值100,其中prep_seq_num = 0
所以在第一种情况下我应该运行:

SELECT SYS_FIELD
      INTO v_start_of_invoice
      FROM BILL
     WHERE TRACKING_ID = v_previous_trackingID
       AND BSCO_CODE_ID = 'PINGPONG'
       AND CHRG_ACCT_ID = v_ACCT_ID
       AND PREP_SEQ_NUM = 0 -- maybe not needed here
       AND ITEM_CAT_CODE_ID=1
       AND PARTITION_KEY = v_prev_partition
       AND SUBPARTITION_KEY = v_prev_subpartition
       AND PRIMARY_IND=0;

在第二种情况下,如果我实际上只有以下内容(prep_seq_num = 0不存在)

Tracking_ID  BSCO_CODE_ID  PREP_SEQ_NUM  ITEM_CAT_CODE_ID PRIMARY_IND SYS_FIELD
    1            PINGPONG        61             5               1        50

我应该从sys_field获取值50,因此运行以下查询:

SELECT SYS_FIELD
      INTO v_start_of_invoice
      FROM BILL
     WHERE TRACKING_ID = v_previous_trackingID
       AND BILL_CODE_ID = 'PINGPONG'
       AND ITEM_CAT_CODE_ID in ('5' , '-100')
       AND PARTITION_KEY = v_prev_partition
       AND SUBPARTITION_KEY = v_prev_subpartition
       AND PRIMARY_IND=1;

我有很多想法,但没有一个真正有效我希望在一个查询中获得最有效/最快速度。 THKS

1 个答案:

答案 0 :(得分:0)

您要寻找的是排名:您更喜欢prep_seq_num = 0 and primary_ind = 0而不是prep_seq_num <> 0 and primary_ind = 1

执行此操作的典型方法是限制条款。这是标准SQL中的FETCH FIRST ROWS,可从Oracle 12c开始提供。另一种选择是ROW_NUMBER,它也是标准的SQL,自从我认为8i以来在Oracle中可用。

select sys_field
  into v_start_of_invoice
from bill
where tracking_id = v_previous_trackingid
  and bsco_code_id = 'PINGPONG'
  and partition_key = v_prev_partition
  and subpartition_key = v_prev_subpartition
  and 
  (
    (
      prep_seq_num = 0 and
      primary_ind = 0 and
      item_cat_code_id = 1 and
      chrg_acct_id = v_acct_id
    )
    or
    (
      prep_seq_num <> 0 and
      primary_ind = 1 and
      item_cat_code_id in (5, -100)
    )
  )
order by case when prep_seq_num = 0 then 1 else 2 end
fetch first 1 row only;

另一个选择是Oracle的KEEP FIRST

select max(sys_field) keep (dense_rank first 
                            order by case when prep_seq_num = 0 then 1 else 2 end)
  into v_start_of_invoice
...

<击>

<击>
order by case when prep_seq_num = 0 then 1 else 2 end
fetch first 1 row only;

<击>

以下是ROW_NUMBER的查询:

select sys_field
  into v_start_of_invoice
from
(
  select 
    sys_field, 
    row_number() over (order by case when prep_seq_num = 0 then 1 else 2 end) as rn
  from bill
  where tracking_id = v_previous_trackingid
    and bsco_code_id = 'PINGPONG'
    and partition_key = v_prev_partition
    and subpartition_key = v_prev_subpartition
    and 
    (
      (
        prep_seq_num = 0 and
        primary_ind = 0 and
        item_cat_code_id = 1 and
        chrg_acct_id = v_acct_id
      )
      or
      (
        prep_seq_num <> 0 and
        primary_ind = 1 and
        item_cat_code_id in (5, -100)
      )
    )
)
where rn = 1;