Newsgroup: it.comp.lang.visual-basic
Titolo: [?] Ricerca primo codice disponibile

Il mio problema e' il seguente: devo trovare il primo codice disponibile
all'interno di una tabella. Nulla di complicato ma quando si tratta di una
tabella contenente 10500 records la cosa diventa mooolto lenta, o per lo
meno per l'operazione che eseguo io.
Io faccio cosi':
codice_disponibile=0
apro la tabella
Do while not tabella.eof
    sql="select count (*) as result from tabella where tabella.codice=" &
codice_disponibile & ""
    ..........
    if RC("RESULT")=0 THEN EXIT FOR
    tabella.movenext
    Codice_disponibile=    Codice_disponibile+1
Loop
Print.Codice_Disponibile
Il problema e' che se il codice disponibile e' "basso" la ricerca e'
immediata ma se il mio codice disponibile deve essere
l'ultimo della colonna +1..... non possa veramente piu'
La query puo' rallentare sicuramente... ma in alternativa potrei fal
looppare il database  n volte finche non trova il dato
Ciao e grazie

...


non ho ben capito ma forse ti basta
select max(codice) from tabella
Lunga Vita e Prosperità

Ciao e grazie ancora per l'interessamento
Forse non mi sono spiegato molto bene e ne approffitto per rivedere il mio
codice di scrittura.....
Dunque il problema e' il seguenta:
- io ho una tabella con il campo codice
- in questa tabella vi sono 10500 records
- questi records devono essere associati ad un codice crescente
- questi records possono essere aggiunti , eliminati o modificati
- in caso di modifica nessun problema in quanto ricerco il record specifico
in base al codice o  altro
- se elimino il record punto il record interessato e lo rimuovo: qui si vede
come si genera un buco di ordinamento
- se aggiungo un record questo deve assumere il codice in base al primo
buco, nel caso io abbia un ordinamento crescente e         completo di tutti
i codici, ovvero da 1 a 10500, il primo codice libero sara' 10500+1.
Ma come faccio a sapere a priori qual e' il primo buco disponibile?
Se ho fortuna e questo e' all'inizio, la ricerca e' molto veloce.... ma
ipotizzando che il primo disponibile sia proprio l'ultimo +1 (in quanto
l'ordinamento e' completo) la ricerca e' molto lenta.
Il tutto mi funziona , il risultato l'ottengo ma un conmto e' ottenerlo in n
secondi ed un altro e' ottenerlo in n/y secondi.
Se io già mi stufo per l'attesa.... figuratevi poi l'utente.
Potrei creare un file con i buchi disponibili, ma questa mi sembra un modo
per aumentare solo codice.... se non vi sono alternative lo utilizzero' ma
prima sono alla ricerca di altre soluzioni
Domandina:    in un loop di una tebella, e' piu' veloce un select count o un
find???
Bye


Se non hai la necessita' di recuperare dei codici intermedi ossia dei
"buchi" la soluzione giusta e' quella proposta da PennyWise, altrimenti hai
poche strade.Comunque :
1) Prova a vedere se hai un indice sul campo Codice ed in caso negativo
crealo.
2) non usare nel tuo while tabella.eof e' + veloce fare cosi' :
   apri la tabella
    tabbella.movelast
    tabella.movefirst
    NumRec = tabella.recordcount
    OldCod = -1        'se x te il codice "0" e' possibile, altrimenti
imposta OldCod = 0
    For i = 0 to NumRec -1
         if i <> tabella("Codice") then
            Codice_disponibile = oldCod+1
            exit For
         end if
         oldCod = tabella("Codice")
         tabella.movenext
    next i
3) Nel caso vuoi perfezionare solamente la tua soluzione, non usare la
count(*) in questo caso non e' indispensabile e pesa di piu' di una :
sql="select  Codice from tabella where Codice = " &  codice_disponibile
se non trova nulla fai quello che devi fare altrimenti vai avanti...........
Fammi sapere.........
Ciao
Ven.

Messa così ho paura che il metodo più veloce sia una tabella con i codici
cancellati da riutilizzare!!
ciao

...


Effettivamente quello di Ven mi sembra il metodo migliore, ma pensandoci ci
potrebbe essere una alternativa che è un misto delle soluzioni: creare una
tabella di codici disponibili riempita però di valori booleani, true per
disponibile false per usato, ovviamente la il primo codice disponibile è
dato dalla posizione del primo true nella tabella e, una volta prelevato,
deve essere impostato a false come deve essere impostato a true quando viene
eliminato. Questa soluzione mi sembra avere alcuni vantaggi: 1); la tabella
occupa poco spazio, anche ammettendo di doverla riempire fino al limite
delle possibilita del campo (ovviamente con una query da eseguire solo al
momento della creazione); 2) la ricerca è estremamente veloce, si tratta di
ricercare il primo valore true magari indicizzato.
Fatemi sapere se è una buona idea, perchè anch'io sto affrontando lo stesso
problema.
ciao a tutti Axel

Scusate ma mi sono ricordato un particolare per velocizzare la query
proposta da Ven: invece di scrivere sql="select  Codice from tabella where
Codice = " &  codice_disponibile .... Provate con  sql="select  Top 1 Codice
from tabella where Codice = " &  codice_disponibile......
la clausola Top 1 dice al motore di ritornare un solo record e questo, a
giudizio di microsoft sembra migliorare molto le prestazioni (solo
informatiche purtroppo)
ciao a tutti
axelmet


------------
Francesco Beccari
frankb@I_HATE_SPAM_interplanet.it


La tua idea non e' male ma se c'e' la possibilita' di modificare la
struttura della tabella allora FORSE sarebbe meglio fare :
1) Modifichi la struttura della tabella, aggiungi un campo booleano ad
esempio lo chiami CANCELLATO.
2) Metti sopra a questo campo un bell'indice.
4) Da access o anche con il VISDATA apri il tuo database ed esegui questo
SQL :
    Update TABELLA set CANCELLATO = FALSE
3) ti fai un banalissimo programmino che ti scorre tutta la tabella ed
inserisce i CODICI mancanti lasciando a Null tutti gli altri valori e
mettendo CANCELLATO = TRUE
4) Modifichi il tuo Programma in modo che quando vai a cancellare un record,
non lo cancelli effettivamente ma imposti CANCELLATO = TRUE e naturalmente
ricordati che quando vai a recuperare un codice cancellato di reimpostare
CANCELLATO = FALSE
5) A questo punto il primo codice libero ti e' dato da :
    "Select TOP 1 Codice From Tabella where cancellato = true Order By
Coidice"
6) Se la query soprastante da un risultato quello e' il codice da prendere,
se non ti ritorna nulla allora devi prendere MAX(CODICE) + 1
7)  Occhio che devi ricordarti poi nelle vari fasi del tuo programma che i
record cancellati sono contrassegnati dal campo CANCELLATO = FALSE , per
intenderci se prima ad esempio per stampare tutta la tabella non ti
preoccupavi di nulla, ora devi ricordarti di prendere solo i record che
hanno CANCELLATO = FALSE
Prova e facci sapere
Ciao
Ven.

A questo punto le cose sono due, o Luigi si è suicidato oppure ha scovato
l'algoritmo piu veloce del mondo ;-)))).
Scusate non è per difendere a tutti i costi la mia geniale intuizione
---(( ,
ma mi sembrava piu semplice la normale tabella booleana da cui prelevare i
codici disponibili con una banale select certo dipende da quale è il limite
del campo codice (spero non un ESAGERATILIONE di TROPPILIARDI).
Forse non ho compreso bene il problema o  probabilmente stiamo dicendo tutti
piu o meno la stessa cosa... se è cosi (tutti la stessa cosa) allora forse
abbiamo trovato il metodo migliore, complimenti a tutti (specialmente a me
bhuuuu).

...




<Ax> wrote in message news:...
 Scusa, infatti mi riferivo a SR (che dopo aver gettato un paio di sassate
č
 scomparso), evidentemente mi si era incastrata la "rotella" del mouse
(Mikey
 Mouse tanto per rimanere in tema disneyano) e mi risultavi il primo della
 lista....
 La tua soluzione infatti mi sembra la piů adatta, io ho solo aggiunto
 che,nel mio caso, al posto della tabella di codici si potrebbe sostituire
 una tabella di valori booleani che diminuisce sensibilmente le dimensioni
 (argomento su cui sono molto sensibile visto che combatto con database
 mastodontici che devo contenere assolutamente su di un CD) e probabilmente
,
 ma questa č solo una sfumatura da pignoli....  č piu veloce nella ricerca
 poichč si raggiunge con una sola select Top 1 senza funzioni di
 raggruppamento tipo max()  min() o Count() per contro č un po piu
complicata
 da implementare.
 Ciao a tutti
 Axelmet