2016-08-03 11 views
0

Ich habe eine Anforderung, das Genehmigungslimit basierend auf der Produktmenge zu erhalten. Zum Beispiel - Wenn die Produktmenge weniger als 10.000 beträgt, wenden Sie sich an die entsprechende Genehmigungsstelle.Bedingte Genehmigungsstufen basierend auf Produkt

  • Wenn das Produkt Menge von mehr als 10000 und kleiner als 50000, erhält dann die entsprechende Genehmigung Person und Person unter 10000 Grenze

  • Wenn das Produkt Menge von mehr als 50000 und kleiner als 100000, dann erhält die entsprechende Genehmigung Person und alle Personen unter 50000 Grenze

  • Wenn das Produkt Menge von mehr als 100.000 und weniger als 500000, erhält dann die entsprechende Genehmigung Person und alle Personen unter 100000 Grenze

Ist es möglich, dies zu erreichen, ohne die Produktmenge und das Genehmigungslimit hart zu codieren, was bedeutet, dass es dynamisch sein sollte, da sich die Werte in der Tabelle ändern.

+0

Ich bin mir nicht sicher, das ist immer noch klar; Können Sie das Ergebnis hinzufügen, das Sie erwarten und was Sie bisher versucht haben?(Auch nicht sicher, warum du/denormierte Daten in 'pos_t' dupliziert hast, aber hoffentlich ist das nur eine Demo) –

+0

Dein Fallausdruck stimmt auf 50000 genau nicht überein, was ich mir vorstelle, ist ein Fehler; Sie brauchen nur die '<' Prüfung in jedem Zweig? Aber damit sollte es den Vorgesetzten 2, 3 und 4 entsprechen; Warum erwartest du, dass es 1 und 2 entspricht? –

Antwort

1

Soweit ich Ihnen nur togather Ihre Tabellen verknüpfen müssen sagen können:

select pos_t.* 
from prod_t 
join pos_t on pos_t.username = prod_t.username 
and pos_t.approval_limit <= prod_t.product_amt 
where prod_t.prod_id = 'BC45' 
and prod_t.product_amt = 50000; 

USERNAME    NAME   POSITION  SUPERIOR_POSITION_LEVEL_ID SUPERIOR_POSITION_NAME SUPERIOR_NAME SUPERIOR_USERNAME SUPERIOR_P APPROVAL_LIMIT 
-------------------- --------------- --------------- -------------------------- ------------------------- --------------- ----------------- ---------- -------------- 
C1256    James   Fin. Analyst        1 Sen.Analyst    Ford   12735     782   10000 
C1256    James   Fin. Analyst        2 Manager     Smith   329822     6218   50000 

Mit product_amt 12000 es gibt nur leitende Position 1 ; für 120000 gibt es 1, 2 und 3 zurück; für 500000 gibt es 1, 2, 3 und 4. Das scheint das zu sein, was Sie beschreiben und erwarten.

Wenn Sie nur die haben prod_id dann können Sie die Pegel für alle Werte erhalten, wobei in diesem Fall benötigen Sie ein distinct:

select distinct pos_t.* 
from prod_t 
join pos_t on pos_t.username = prod_t.username 
and pos_t.approval_limit <= prod_t.product_amt 
where prod_t.prod_id = 'BC45'; 

USERNAME    NAME   POSITION  SUPERIOR_POSITION_LEVEL_ID SUPERIOR_POSITION_NAME SUPERIOR_NAME SUPERIOR_USERNAME SUPERIOR_P APPROVAL_LIMIT 
-------------------- --------------- --------------- -------------------------- ------------------------- --------------- ----------------- ---------- -------------- 
C1256    James   Fin. Analyst        1 Sen.Analyst    Ford   12735     782   10000 
C1256    James   Fin. Analyst        4 Chief Executive   Scott   13457     2987   500000 
C1256    James   Fin. Analyst        2 Manager     Smith   329822     6218   50000 
C1256    James   Fin. Analyst        3 General Manager Finance Jack   23512     727   100000 

Oder die höchsten product_amt für die prod_id finden und zu diesem beschränken, die Sie erhalten die gleiche Antwort, aber wird effizienter, zum Beispiel mit so etwas wie:

select pos_t.* 
from (
    select max(username) keep (dense_rank last order by product_amt) as username, 
    max(product_amt) as product_amt 
    from prod_t 
    where prod_id = 'BC45' 
) prod_t 
join pos_t on pos_t.username = prod_t.username 
and pos_t.approval_limit <= prod_t.product_amt; 

USERNAME    NAME   POSITION  SUPERIOR_POSITION_LEVEL_ID SUPERIOR_POSITION_NAME SUPERIOR_NAME SUPERIOR_USERNAME SUPERIOR_P APPROVAL_LIMIT 
-------------------- --------------- --------------- -------------------------- ------------------------- --------------- ----------------- ---------- -------------- 
C1256    James   Fin. Analyst        1 Sen.Analyst    Ford   12735     782   10000 
C1256    James   Fin. Analyst        2 Manager     Smith   329822     6218   50000 
C1256    James   Fin. Analyst        3 General Manager Finance Jack   23512     727   100000 
C1256    James   Fin. Analyst        4 Chief Executive   Scott   13457     2987   500000 

Oder wenn Sie die passenden Daten wollen für jeden product_amt zur gleichen Zeit, Sie können einfach die distinct weglassen und die Menge, damit Sie wissen, welche es passt:

select prod_t.product_amt, pos_t.* 
from prod_t 
join pos_t on pos_t.username = prod_t.username 
and pos_t.approval_limit <= prod_t.product_amt 
where prod_t.prod_id = 'BC45'; 

PRODUCT_AMT USERNAME    NAME   POSITION  SUPERIOR_POSITION_LEVEL_ID SUPERIOR_POSITION_NAME SUPERIOR_NAME SUPERIOR_USERNAME SUPERIOR_P APPROVAL_LIMIT 
----------- -------------------- --------------- --------------- -------------------------- ------------------------- --------------- ----------------- ---------- -------------- 
    120000 C1256    James   Fin. Analyst        1 Sen.Analyst    Ford   12735     782   10000 
    500000 C1256    James   Fin. Analyst        1 Sen.Analyst    Ford   12735     782   10000 
     50000 C1256    James   Fin. Analyst        1 Sen.Analyst    Ford   12735     782   10000 
     12000 C1256    James   Fin. Analyst        1 Sen.Analyst    Ford   12735     782   10000 
    120000 C1256    James   Fin. Analyst        2 Manager     Smith   329822     6218   50000 
    500000 C1256    James   Fin. Analyst        2 Manager     Smith   329822     6218   50000 
     50000 C1256    James   Fin. Analyst        2 Manager     Smith   329822     6218   50000 
    120000 C1256    James   Fin. Analyst        3 General Manager Finance Jack   23512     727   100000 
    500000 C1256    James   Fin. Analyst        3 General Manager Finance Jack   23512     727   100000 
    500000 C1256    James   Fin. Analyst        4 Chief Executive   Scott   13457     2987   500000 
+0

Ich kann prod_id nur als Parameter übergeben – user75ponic

+0

Alle 'prod_t' Reihen in Ihrem Beispiel haben die gleiche' prod_id'. Wenn Sie also nur nach dieser Spalte filtern, welche Ausgabe möchten Sie? Die 'pos_t' entspricht der höchsten' product_amt' für diese 'prod_id'? All das passt zu jedem Betrag (was wird das Gleiche sein)? –

1

Ich glaube, Sie brauchen etwas wie folgt aus:

with amounts as (
    select username, nvl(lag(product_amt) over (order by product_amt), 0) amt1, 
     product_amt amt2 
    from prod_t where username = 'C1256' and prod_id = 'BC45') 
select amt1, amt2, approval_limit, superior_name, 
    case when amt1 < approval_limit then 'PRIMARY' else 'SECONDARY' end as type 
    from amounts 
    join pos_t on amounts.username = pos_t.username and approval_limit <= amt2 
    where amt1 < 50000 and 50000 <= amt2 
    order by amt2, approval_limit desc; 


========================================================================= 


     AMT1  AMT2 APPROVAL_LIMIT SUPERIOR_NAME TYPE 
---------- ---------- -------------- ---------------- --------- 
    12000  50000   50000 Smith   PRIMARY 
    12000  50000   10000 Ford    SECONDARY 

Die Abfrage zeigt Haupt Zustimmung Person (en) in der Spalte list1 und Sekundär in list2, von ihrem Niveau sortiert. Die Zuweisung wird dynamisch abhängig von Werten in prod_t erstellt.

with amounts as (
    select row_number() over (order by product_amt) rn, 
     nvl(lag(product_amt) over (order by product_amt), 0) amt1, 
     product_amt amt2 
    from prod_t) 
select rn, amt1, amt2, 
     (select listagg(superior_name, ',') 
       within group (order by pos_t.superior_position_level_id desc) 
      from pos_t where amt1 < approval_limit and approval_limit <= amt2) list1, 
     (select listagg(superior_name||' ('||approval_limit||')', ',') 
       within group (order by pos_t.superior_position_level_id desc) 
      from pos_t where approval_limit <= amt1) list2 
    from amounts 
    order by rn 


========================================================================= 


    RN  AMT1  AMT2 LIST1  LIST2 
------ ---------- ---------- --------- ------------------------------------------ 
    1   0  12000 Ford  
    2  12000  50000 Smith  Ford (10000) 
    3  50000  120000 Jack  Smith (50000),Ford (10000) 
    4  120000  500000 Scott  Jack (100000),Smith (50000),Ford (10000) 

Ist es möglich, ohne mit und als Aussagen zu tun?

Ja, wie hier:

select amt1, amt2, approval_limit, superior_name, 
    case when amt1 < approval_limit then 'PRIMARY' else 'SECONDARY' end type 
    from (
    select username, nvl(lag(product_amt) over (order by product_amt), 0) amt1, 
      product_amt amt2 
     from prod_t where username='C1256' and prod_id = 'BC45') amounts 
    join pos_t on amounts.username = pos_t.username and approval_limit <= amt2 
    where amt1 < 50000 and 50000 <= amt2 
    order by amt2, approval_limit desc 
Verwandte Themen