2013-03-13 5 views
0

je la requête récursive suivante qui irait à 11g, mais ne sont pas pris en charge dans la base de données Oracle 10g:Oracle 10g récursive requêtes

with st as (
    select 
     rownum id, 
     case 
      when rownum-1 < 1 then null 
      else rownum-1 
     end parent_id, 
     customer, 
     tickets 
    from tickets 
), 
st2(id, parent_id, customer, tickets, offset) as (
     select 
      id, parent_id, shuffler_id, subno, contrno, tickets, 0 offset 
     from st 
     where id = 1 
    union all 
     select 
      st2.id, st2.parent_id, st2.tickets, (st.tickets + st.offset) offset 
     from st, st2 
     where st2.parent_id = st.id 
) 
select * from st2 

Ce que je suis en train de faire est de calculer un décalage pour chaque ligne en fonction sur sa colonne précédente les colonnes tickets et offset (même colonne calculée), et je commence la première ligne avec un décalage de 0; le fait que je doive dépendre d'une colonne que je calcule lors de l'exécution de la requête nécessite une récursivité.

La question est la requête ci-dessus ne sont pas pris en charge dans Oracle 10g, donc j'ai essayé d'utiliser connect by au lieu qui fonctionne, mais la partie est laid, il est extrêmement inefficace:

with st as (
    select 
     rownum id, 
     case 
      when rownum-1 < 1 then null 
      else rownum-1 
     end parent_id, 
     customer, 
     tickets 
    from tickets 
) 
select 
    id, 
    parent_id, 
    customer, 
    tickets, 
    (
     select nvl(sum(tickets), 0) from st 
     where level < x.id 
     start with id = 1 
     connect by prior id = parent_id 
    ) offset 
from st x 

Utilisation de la 2ème requête que je suis sommer toutes les lignes précédentes, ce qui fait le travail mais est également redondant et je ne peux pas compter sur quand cette table se développe à des millions d'enregistrements.

Une idée sur la façon de mettre en œuvre quelque chose de similaire à la première requête dans la base de données Oracle 10g?

Répondre

3
select 
    id, 
    customer, 
    tickets, 
    nvl(
     sum(tickets) over (
     order by id rows between unbounded preceding and 1 preceding 
    ), 0) as offset 
    from ( 
    select 
     rownum id, 
     customer, 
     tickets 
    from tickets 
) 

ou même plus courte (sans introduire id s)

select 
    customer, 
    tickets, 
    nvl(
     sum(tickets) over (
     order by rownum rows between unbounded preceding and 1 preceding 
    ), 0) as offset 
    from tickets 
+0

Je suis curieux, ce semble que ce soit la somme encore toutes les lignes précédentes pour chaque rangée pour calculer le décalage, qui est toujours redondant mais beaucoup plus rapide que ce que j'ai fait! Y a-t-il un moyen de rendre cela encore plus rapide en réutilisant le décalage déjà calculé de la ligne précédente? – abstractpaper

+0

@abstractpaper - la fonction analytique 'sum' a une complexité de calcul optimale. Je ne sais pas comment le rendre encore plus rapide. –

+0

Nevermind c'est optimal et ça fait ce que je veux, c'est réutiliser les offsets précédents! – abstractpaper