• User Attivo

    [ASP] funzione ricorsiva e paginazione

    Salve a tutti ho una questione che non riesco a risolvere.
    Uso una funzione ricorsiva per recuperare dei record relazionati a n livelli di zone.
    Avendo più select sql non posso utilizzare la classica paginazione basata su Absolutepage, PageCount, pageSize ecc.. come posso fare ?

    riporto il codice della funzione:

    Function immobiliInseriti(zonaID)

      dim strq, rscat, rsfigli
    
      	strqMacro = "Select * from nomeTabella where id = "&zonaID
    
     
      set rscat=cn.execute(strqMacro)
     
      Do while not rscat.eof
    			
                     str = str&rs("nome_immobile") ecc...
    	
       rscat.MoveNext
       Loop
                
                         strq = "Select *  From nomeTabella where idGen = "&id
    
    	set rsfigli=cn.execute(strq)
    	while not rsfigli.eof
    		 str = str& immobiliInseriti(rsfigli("Tbl_Zone.id"))'
    	  rsfigli.movenext
    	wend
    	
      immobiliInseriti = str
    

    end function


  • User Attivo

    Ok ci riprovo esprimendomi in maniera diversa

    (Tra l'altro scusate ma ho notato solo ora con la lucidità mattutina che quella che ho postato sopra contiene errori, ma non è questo il punto)

    Ho una tabella con la classica struttura id - nomeCat - idGen
    contiene n livelli, quindi tutto in una sola tabella.

    questa tabella è relazionata a degli articoli.
    se sono nella cat_A che contiene a sua volta cat_A1 e che a sua volta ha un'altra sottocat es, cat_A2 vorrei poter recuperare tutti gli articoli appartenenti a Cat_A e alle sue sottocategorie.

    Per farlo uso una funzione ricorsiva

    Usando questa funzione che richiama se stessa però non ho una Select unica sugli aricoli e quindi ho difficoltà nel paginare.

    Come posso risolvere, mantenendo la stessa struttura per la tabella delle cat ?


  • User Attivo

    Ciao scura 🙂

    prova a cambiare logica, ovvero fai in modo che la tua funzione, invece di restituirti la stringa con i risultati, ti restituisca la stringa SQL somma di tutte le query, attraverso UNION.

    In soldoni: fai in modo che alla fine la funzione ti restituisca qualcosa del genere:

    
    strSQL = "Select * from nomeTabella where id = 1 UNION Select *  From nomeTabella where idGen = 2 UNION Select *  From nomeTabella where idGen = 3"
    
    ```Eseguendo questa query avrai un recordset unico e paginabile.
    
    Fammi sapere :)
    
    :ciauz:

  • User Attivo

    grazie Madai provo subito

    😉


  • User Attivo

    Sorge un problemino:

    function EsploraZoneArray(id)

      dim strq, rscat, rsfigli
    
      strq = "SELECT * from Tbl_Zone WHERE id = "&id
     
      set rscat=cn.execute(strq)
      
      if not rscat.eof then
    			
    		str = str & rscat("id")&"*"
    	
      strq = "SELECT * from Tbl_Zone WHERE idGen = "&id
    	
    	set rsfigli=cn.execute(strq)
       
    	while not rsfigli.eof
    	  response.write EsploraZoneArray(rsfigli("id"))
    	  rsfigli.movenext
    	wend
      end if
       EsploraZoneArray = str
    

    end function

    Sub immobiliInseritiZona(zonaID)
    Dim Str_ArrayZone
    Str_ArrayZone = EsploraZoneArray(zonaID)
    ArrayZone = Split(Str_ArrayZone,"*")

    set rs = Server.CreateObject("ADODB.Recordset")
    sSql = "Select * from Tbl_Immobili Where zonaID = "&zonaID
    
    For i = 0 to (Ubound(ArrayZone) - 1)
    	sSql = sSql &" UNION Select * From Tbl_Immobili where zonaID ="&ArrayZone(i)
    	i = i+1
    Next
    
    response.write sSql
    

    end Sub

    EsploraZoneArray(zonaID) è la lista degli id delle zone per le quali devo recuperare degli annunci,equivale a una cosa del tipo = 1740394138434257545655*
    ma il problema è che non lo splitta, non lo trasformama in array, lo stampa....


  • User Attivo

    Madai, immagino succeda la stessa cosa se invece di recuperare l'array con gli id delle zone da cercare recupero, come dicevi te, la stringa sQl da interrogare...me la stampa invece di eseguirla...come posso risolvere ?


  • User Attivo

    Devi usare una funzione non una sub

    e alla fine della funzione metti

     immobiliInseritiZona = sSql
    

  • Moderatore

    Ho una tabella con la classica struttura id - nomeCat - idGen
    contiene n livelli, quindi tutto in una sola tabella....

    credo che una soluzione efficiente sia quella di aggiungere il campo catLevel che indica il livello di annidamento delle categorie:
    0 -> Categoria principale
    1 -> Sub Categoria di livello1
    2 -> Sub categoria di Livello2
    ....

    e poi utlizzare una query parametrica come la seguente:

    
    select id, idGen, first(nomeCat), count(id) as NumItemInSubCat from
    MyTable LEFT JOIN MyTable
    on MyTable.id=MyTable.idGen
    Group By id, idGen
    Having CatLevel = @Actual_Level
    Order BY first(nomeCat)
    
    

    La precedente query è utile ad estrarre anche il numero di sottogategorie "attuali" da inserire accanto ai nomi delle categorie-Link della struttura ad albero (TreeView di ASP.NET o un usuale menu verticale navigabile in DHTML)

    :ciauz:


  • User Attivo

    @madai said:

    Devi usare una funzione non una sub

    e alla fine della funzione metti

    immobiliInseritiZona = sSql
    

    Sub o function ho provato entrambe, ma il problema è nella funzione ricorsiva...

    while not rsfigli.eof
    response.write EsploraZoneArray(rsfigli("id"))
    rsfigli.movenext
    wend

    response.write sSql mi serve per stampare la query che mi hai suggerito di ricavare, per vedere se corretta, da lì poi ovviamente sarebbe una passeggiata, se EsploraZoneArray non fosse stampato, ma fosse solo una stringa da scomporre il gioco sarebbe fatto, anche se mi rendo conto che la soluzione di Paocavo è di tuttaltra eleganza 🙂

    Vorrei provare a capirla meglio...non ho mai fatto una cosa così ma mi piace usare questa struttura per le n categorie, quindi devo migliorarla se voglio continuare ad usarla

    Prima di modificare la tabella con id-idGen

    aggiungendo Livello vorrei capire se posso recuperare lo stesso la lista di tutte le sottoCat a partire da un id (ovviamente con il livello avrei la possibilità di recuperare i dati in maniera ordinata e non solo se non ho capito male)

    es. una cosa di questo tipo

    "Select id, idGen, first(id), count(id) as NumItemInSubCat from Tbl_Zone LEFT JOIN Tbl_Zone on Tbl_Zone.id=Tbl_Zone.idGen Group By id, idGen"

    ho provato ma ho un errore : Syntax error in JOIN operation

    (considera che il nome delle categorie è tradotto in più lingue in un'altra tabella)


  • Moderatore

    @scura said:

    Sub o function ho provato entrambe, ma il problema è nella funzione ricorsiva...

    Infatti credo che il problema sia proprio nella ricorsività degli accessi al DB, in pratica si aprono n RecordSet successivi sullo stesso gruppo di Tabelle prima che i precedenti vengano chiusi. E questo crea parecchi problemi ad Access.

    La query che hai postato, e che ti restituisce l'errore di sintassi, provala prima ad eseguirla sul DB, probabilmente dovrai rinominare solo nella query sql una delle "due" tabelle che hanno lo stesso Nome, ad esempio:

    
    Select id, idGen, first(id), count(id) as NumItemInSubCat 
    from Tbl_Zone LEFT JOIN Tbl_Zone as Tbl_Zone2 
    on Tbl_Zone.id=Tbl_Zone2.idGen 
    Group By id, idGen
    
    

    :ciauz:


  • User Attivo

    Si così l'errore è risolto, però eseguendo la query non riesco a recuperare le categorie oltre il secondo livello...motivo per cui usavo la ricorsione....sbaglio ?


  • User Attivo

    Allora...magari a quelcuno potrà essere utile

    risolta la questione utilizzando il suggerimento di Madai...
    Ho cambiato la funzione ricorsiva:

    
    function EsploraZoneArray(id)
     
     strq = "SELECT * from Tbl_Zone WHERE id = "&id
     set rscat=cn.execute(strq)
     
     if not rscat.eof then
        str = str & rscat("id")&"*"
        strq = "SELECT * from Tbl_Zone WHERE idGen = "&id
        set rsfigli=cn.execute(strq)
        while not rsfigli.eof
             str = str & EsploraZoneArray(rsfigli("id"))
             rsfigli.movenext
        wend
     end if
     EsploraZoneArray = str
    end function
    
    

    Approfitto della questione sollevata per fare domande e cercare di colmare le mie lacune 🙂

    Ho trovato questo articolo "Stored Procedure ricorsive su SQL-Server"

    Provato con mssql, mi chiedevo:
    Una cosa del genere si può fare anche con access ?


  • User Attivo

    Effettivamente come anticipava Paocavo la ricorsione sembra appesantire in maniera evidente ... vorrei capire meglio: con asp e db Access dunque devo dimenticare di fare operazioni simili ??? Non è possibile fare niente neanche utilizzando le Stored Queries ??? .... se così fosse l'unica soluzione sembra cambiare db


  • Moderatore

    @scura said:

    Effettivamente come anticipava Paocavo la ricorsione sembra appesantire in maniera evidente ... vorrei capire meglio: con asp e db Access dunque devo dimenticare di fare operazioni simili ???

    Se la profondità di annidamento delle sub-categorie "N" è maggiore di 3 (3 livelli di annidamento) allora, secondo me, è fortemente sconsigliabile MS Access.
    Se invece usi SQL-Server allora puoi andare più tranquilla con Stored procedures ricorsive ad-hoc che generano recordset gerachici.

    Non è possibile fare niente neanche utilizzando le Stored Queries ??? .... se così fosse l'unica soluzione sembra cambiare db

    Da provare...ma se rimani in MS Access la soluzione migliore è quello di aggiungere un campo che indichi il livello di annidamento e interrogare il DB in maniera interattiva in funzione del livello "attuale".
    :ciauz:


  • User Attivo

    Ciao Paocavo

    Inserire il livello di anidamento è un buon consiglio da seguire secondo me anche se si usa mssql, che tra l'altro avevo suggerito in fase iniziale. Come dire..l'avevo detto io 🙂 alla quattrocchi, ma hanno voluto partire con access, cosa vuol dire partire già sapendo che prima o poi .. non chiedermelo, io sarei partita con mssql.

    Con le stored queries ho fatto un piccolo test e ho notato che a occhio si guadagna un pò in prestazioni. ( Esiste un metodo più preciso per test di verifica prestazioni ? ) In particolare richiamo le SQ passando 2 parametri (nel mio caso lingua e catID) per generare l'albero. Ma comunque la ricorsione cicla il codice asp/vbscript passando ogni volta valori diversi alla SQ, quindi aprendo tanti recordset ecc... Ora mi chiedevo se fosse possibile fare una sorta di Stored Queries Ricorsiva (tipo la stored procedure ricorsiva dell'esempio del link sopra che tra l'altro usa i livelli di annidamento)... anche se dubito si possa fare...

    Approfitto di questa discussione per chiedere una cosa: proprio ieri parlavo con uno sviluppatore (nuova collaborazione) al quale vorrei comissionare lo sviluppo di un prog abbastanza complesso del quale vorrei lavarmi le mani 🙂
    Mi chiede tantissimi soldi per sviluppare il tutto... ma io ci sto perchè effettivamente è complesso il prog e voglio un buon prodotto...ad un certo punto gli dico che costi devo prventivare per il piano hosting ed esce fuori che svilupperà tutto in access perchè secondo lui meglio (dice + veloce) di MSSQL e MYSQL....

    Ovvio sto pensando se affidarmi o no a questa persona per lo sviluppo del lavoro 🙂 ....ma è possibile una cosa del genere ???