2016-12-15 5 views
0

Ich habe einen Cursor, der Rechnungen aller Personen nach ihrem Familiennamen gruppiert enthält. Jetzt möchte ich dynamisch prüfen, welcher Familienname eine offene Rechnung dagegen hat. Für z. Es gibt Adams und Perry Familie und viele mehr. Der Cursor hat Werte für alle Mitglieder der Familien, wobei eine Spalte der Familienname ist. Jetzt schaue ich nach dem ausstehenden Betrag, ich finde, es ist einer in adams family. Jetzt möchte ich, dass mein Cursor alle Mitglieder der Adams-Familie anzeigt, damit ich die Rechnung an die anderen Mitglieder der Familie verteilen kann.Cursor mit wo Bedingung

CURSOR individual_cur is 
select name,family_name, bill from table1; 

CURSOR family_cur is 
    select family_name from table1; 

    for temp in family_cur loop 
    select sum(bill) into extra_bill where family_name is temp.family_name; 

    if extra_bill <>0 then 

    -- Now here I want 
    for temp1 in individual_cur loop *where family_name is temp.family_name* 

    -- How to do this. 
    end loop; 
+1

Es gibt absolut keine Notwendigkeit, einen langsamen Cursor für diesen Einsatz . Dies kann mit einer einzigen SQL-Abfrage durchgeführt werden –

+0

@a_horse_with_no_name können Sie mir dabei helfen? http://stackoverflow.com/questions/41541100/fetch-table-name-from-a-column-for-from-klause – Akshay

Antwort

1

Hier ist ein Beispiel

declare 
    -- add family name as parameter 
    -- and use in where clause 
    cursor individual_cur(p_family_name table1.family_name%type) is 
     select name 
      ,family_name 
      ,bill 
     from table1 
     where family_name = p_family_name; 

    --group by family 
    -- and filter on sum(bill)<>0 
    cursor family_cur is 
     select family_name 
     from table1 
     group by family_name 
     having sum(bill)<>0; 
begin 

    for temp in family_cur 
    loop 
     -- select individuals from this family 
     for temp1 in individual_cur(temp.family_name) 
     loop 

      -- do something 
     end loop; 
    end loop; 
end; 

Oder in nur einer Abfrage

select name 
     ,family_name 
     ,bill 
    from table1 
    where family_name in (select family_name 
         from table1 
         group by family_name 
         having sum(bill)<>0) 
+0

hey können Sie mir dabei helfen? http://stackoverflow.com/questions/41541100/fetch-table-name-from-a-column-for-from-klause – Akshay

0

Ich gehe davon aus, was Sie zu tun versuchen ist Durchschnitt errechnet die Rechnung über die alle Familienmitglieder? Wenn ja, dann kann dies in einer einzigen Abfrage erfolgen:

WITH table1 AS (SELECT 'bob' NAME, 'jones' family_name, 0 bill FROM dual UNION ALL 
       SELECT 'jane', 'jones', 100 bill FROM dual UNION ALL 
       SELECT 'fred', 'jones', 50 bill FROM dual UNION ALL 
       SELECT 'bill', 'smith', 0 bill FROM dual UNION ALL 
       SELECT 'brenda', 'smith', 60 bill FROM dual UNION ALL 
       SELECT 'jill', 'smith', 0 bill FROM dual UNION ALL 
       SELECT 'bob', 'ingles', 0 bill FROM dual UNION ALL 
       SELECT 'carol', 'ingles', 0 bill FROM dual UNION ALL 
       SELECT 'rob', 'carolgees', 200 bill FROM dual) 
-- end of mimicking your table1 with sample data in it - you wouldn't need this 
-- see the SQL below 
SELECT NAME, 
     family_name, 
     bill, 
     AVG(bill) OVER (PARTITION BY family_name) split_bill 
FROM table1; 

NAME FAMILY_NAME  BILL SPLIT_BILL 
------ ----------- ---------- ---------- 
rob carolgees   200  200 
carol ingles    0   0 
bob ingles    0   0 
fred jones    50   50 
bob jones    0   50 
jane jones    100   50 
jill smith    0   20 
bill smith    0   20 
brenda smith    60   20 

Dies verwendet die AVG() analytische Funktion, die Rechnung über alle Mitglieder in der Familie zu teilen, ohne die Zeilen wie die AVG() Aggregatfunktion zu Komprimieren tun würde.

Wenn Sie dann zu aktualisieren tabelle1 notwendig, um die gemeinsamen Rechnungen zu reflektieren, könnten Sie dann stecken Sie die obige Abfrage in eine MERGE Anweisung, so etwas wie:

merge into table1 tgt 
    using (select name, 
       family_name, 
       bill, 
       avg(bill) over (partition by family_name) split_bill 
     from table1) src 
    on (tgt.name = src.name and tgt.family_name = src.family_name) 
when matched then 
update set tgt.bill = src.split_bill 
where tgt.bill != src.split_bill; 
+0

hey können Sie mir dabei helfen? http://stackoverflow.com/questions/41541100/fetch-table-name-from-a-column-for-from-clause – Akshay

Verwandte Themen