Newsgroup: it.comp.lang.visual-basic
Titolo: [?] vb6 - ADO e Access velocita ricerca

Devo fare una serie di ricerche pesanti , anzi lunghe e ripetitive, su 
tabella di database access con circa 12000 righe
In pratica devo contare quante volte una stringa ( presente in un'altra 
tabella) e' contenuta in una colonna
Ora faccio cosi' apro il rs con tutto e applico un filter ogni volta con la 
stringa voluta
rs.Filter = "[colonna] Like '*[PAROLA]*' "
Poi controllo la recordcount e se ho > 0 allora esiste !
Ma per quanto veloce sia  .... e' comunque lento ma magari e' unamia idea.
Pensavo di provare i metodi di ADo Find o Seek ma non so se rallento / 
accelero
Consigli ?
Grazie mille 

 ha scritto nel messaggio
news:43bbba80$0$1069$4faf...@reader2.news.tin.it...

Non dici la cosa più importante, ossia se il file di database è locale o in
rete.
Se è in rete, la tua procedura è probabilmente la migliore, nel senso che
effettui un unico trasferimento dei dati aprendo il recordset una tantum, e
poi lavori localmente.
Se invece è in locale, potresti provare con
Dim Occorrenze as Long
Occorrenze=AdoConnection.Execute("SELECT COUNT(1) FROM TABELLA WHERE COLONNA
LIKE '%" & Replace$(VarParola,"'","''") & "%'").Fields.Item(0).Value
If Occorrenze>0 then...
Ciao
Alberto

 If Occorrenze>0 then...
Il Db e' in locale
Ho provato il tuo metodo
Ma purtroppo sembra non funzionare. Cioe' la query restituisce sempre 0
Ho anche sostituito i caratteri jolly con gli asterischi ma niente *
L'ho lanciata da access e nemmeno da li ottengo risultato .... sempre zero !
Quindi "magari" la query e' incorretta. o dove posso aver sbagliato
Riporto le mie tabelle e nomi campi
sParola = "Amico mio"  ' >Variabile Parola da cercare
test2 > nome tabella dove cercare
elenco > nome campo dove cercare
Occorrenze = adoC.Execute("SELECT COUNT(1) FROM test2 WHERE elenco LIKE '%" 
& Replace$(sParola, "'", "''") & "%'").Fields.Item(0).Value
Ho anche pensato di mettere tutto maiuscolo per evitare problemi col LIKE
Ma non ho avuto niente di piu' del solito 0 dove sbaglio .
Nota: sParola esiste in 4 record  ! 

 L'ho lanciata da access e nemmeno da li ottengo risultato .... sempre zero !
Ho creato una tabella che si chiama Test2, con una colonna 'elenco' di 
tipo testo.
Ho inserito alcune parole a caso, fra cui alcuni 'pippo' e alcuni 
'paperino'.
Questa cosa, eseguita in una finestra Sql di Access, funziona e 
restituisce il numero corretto:
SELECT COUNT(1)
FROM TEST2
WHERE ELENCO LIKE '*pippo*'
Come vedi, ho dovuto mettere gli asterischi (non uso Access, mi ero 
confuso).
Ma con gli asterischi funziona (attenzione: è case sensitive!).
Ciao
Alberto
-- 
A questo punto hanno trovato un muro,
un muro duro, molto molto duro,
che siamo noi.

 (attenzione: è case sensitive!).
Bugia.
Ma da dove mi è uscita?


 Albe V° scriveva il 04/01/2006 :
OK funziona e non e' case sensitive
MA .. ,e qua non capisco perche', se la colonna elenco contiene una stringa 
"strana" ovvero un elenco di termini ( perche' lo dico io che sono termini) 
separati dal Pipe e racchiusi fra quadre non funziona
Magari e' colpa di access e dei cartteri [] e |
Es:  [UN]|[ANGELO]|[CADUTO]
Grazie ancora per la pazienza. 

 Magari e' colpa di access e dei cartteri [] e |
Si, quello dipende dalla sintassi del Like, che utilizza appunto le 
quadre e i pipe come caratteri speciali (l'asterisco è solo uno dei 
caratteri speciali del Like).
Verifica sull'help di access, forse basta raddoppiarli come gli 
apicini.
Ciao


 Verifica sull'help di access, forse basta raddoppiarli come gli apicini.
Trovato... Riporto per completezza
La stringa deve essere composta cosi' :  [[]UN]|[[]ANGELO]
Ovvero il carattere [  deve essere racchiuso tra quadre, perche' e' un 
carattere jolly
Questo vale solo nelle Query passate su access o per i adoConnection.Execute 
etc...
Se si usa il filter offerto da ADO allora funziona anche senza racchiudere 
nulla  cosi' :  [UN]|[ANGELO]
Grazie ancora ad Albe V. 

 nulla  cosi' :  [UN]|[ANGELO]
Bene.
Ma le performance (che era poi il problema iniziale)?



Ho avuto da festeggiare.... e quindi riprendo solo ora.
Testato , con un timer anche se non credo che sia la soluzione migliore, per 
processare la stessa quantità di dati ed eseguire il codice nel caso di 
StringaTrovata il metodo Connessione.Execute ci mette 9 minuti circa, mentre 
il ADO.Filter ce ne mette 16.
Per essere un po' piu' precisi sono 328 * 328 interrogazioni ( 107584 
combinazioni totali) eseguite su una tabella di 359 righe.
Intel P4 3ghz 512MB ram... non so se sono prestazioni ottimali ?
Commenti o ulteriori consigli ?

Dopo dura riflessione, Elian ha scritto :

Beh, purtroppo la parola da cercare la conosce il codice VB.
Se le parole da cercare fossero record di una tabella, con qualche join 
potresti avere il risultato completo in tempi dell'ordine dei secondi.



Ma le parole sono record di tabella ! cioe' piu' o meno.
Io ho una tabella con il testo da esaminare "test"
...campo da esaminare "testo"
Poi ho una tabella "Wording" -> creata da una precedente elaborazione con il 
conteggio delle parole
Parola = testo
Istanze= numero
Ora io voglio creare Wording2, Wording3 etc.... cioe' l'unione delle x 
parole ( 328 * 328) in modo da formare una stringa.
per evitaremi problemi di spazi e punteggiatura varia ( che non mi 
interessano) ho rielaborato la colonna "testo" mettendo le [] e separando i 
campi con il Pipe | chiamandola "elenco"
Esempio di  tabella test cosi' vediamo se riesco a rendere l'idea:
testo                   !          elenco
----------------- !--------------------------------
Oggi sono felice  !   [OGGI]|[SONO]|[FELICE]
Ieri eri felice        !  [IERI]|[ERI]|[FELICE]
....
Nella Wording le parole sono senza [] ma questo non e' un problemone...
parola  ! istanze
------- ! -------
OGGI   !   1
SONO  !   1
FELICE !  2
IERI       !  1
....
Mi sono creato una lista di combinazioni da 2 parole ( una collection di 
array) e passavo di volta in volta alla Conn.Execute la "stringa" 
[Parola1]|[Parola2]
Ora riempire una tabella da VB con le combo da 2 e 3 etc... lo so fare e ci 
mette pure poco.
Ma per come costruire la Query di "ricerca" ...beh ho proprio bisogno di 
aiuto e sempre se si puo' fare.

 [Parola1]|[Parola2]
Beh, devo dire che si capisce veramente poco.
Comunque, se Test.TESTO è l'elenco delle 'frasi' in cui cercare, e 
Elenco.Parola è l'elenco delle parole, da concatenare a due a due e 
cercare nella tabella Test (anche se non capisco esattamente cosa tu 
intenda con le combinazioni, cioè, nell'esempio riporti le occorrenze 
di parole singole...), puoi fare una cosa del tipo:
SELECT ELENCO_A.PAROLA AS PAROLA_1, ELENCO_B.PAROLA AS PAROLA_2,
SUM(CASE
     WHEN TEST.TESTO LIKE '%'+ELENCO_A.PAROLA+'%' AND  TEST.TESTO LIKE 
'%'+ELENCO_B.PAROLA+'%'
                THEN 1
     ELSE 0
     END) AS OCCORRENZE
FROM
ELENCO AS ELENCO_A
FULL OUTER JOIN ELENCO AS ELENCO_B
ON 1=1
FULL OUTER JOIN TEST
ON 1=1
Il discorso delle concatenazioni non mi è assolutamente chiaro. 
Nell'esempietto qui sopra, non importa l'ordine delle parole (cioè, 
"CASA" e "MAMMA" ti restituisce un'occorrenza sia per "LA CASA DELLA 
MAMMA" che per "LA MAMMA VA A CASA", ma si può anche gestire l'ordine 
senza particolari difficoltà).
Questa qui sopra è la sintassi TSQL per Sql-Server, credo che per 
Access il full outer join si possa fare con una semplice virgola, e il 
Case lo sostituisci con un IIF.


 sostituisci con un IIF.
Eccomi qua. Dopo aver rielaborato il tutto sono giunto a:
Su Access non esiste una vera FULL OUTER JOIN, ma inserendo brutalmente le 
tabelle interessate senza inserire join "sembra" di ottenere lo stesso 
risultato.
il IIf  funziona
il risultato totale e' Uguale come numero di record, ma le occorrenze invece 
no, perche' se la stringa cercata si ripete piu' volte all'interno del testo 
con il SUM la conto una volta sola (e' una piccolezza ma  bisogna dirlo.)
Provato da debug mi pareva lento, ho provato limitandomi solo ad alcuni 
record per fare le prove e poi dopo che ho visto che funzionava l'ho 
lanciato sul tutto.
Morale e' piu' lenta di quella adottata prima:
1° soluzione ( la prima) con l'utilizzo di ado.Filter  ~ 16 minuti
2° soluzione connessione.execute " SELECT COUNT...."  ~ 9 minuti
3° soluzione connessione.Execute " select + sum" + accodamento a tabella 
fatto dalla query (visto che ci sono) ~ 13 minuti
Magari sarebbe piu' veloce se girasse su un "motore" che supporta Full Outer 
Join.
Comunque la media rimane li.. dai 10 ai 20 minuti circa ! Quindi i 9 minuti 
mi sembrano coerenti e ottimali. Anche se sono prove "casereccie".
Se avete altri consigli sono bene accetti altrimenti tengo buono il metodo 2 
e mi lancio all'esame di stringhe piu' complesse e corpose ( da 3 parole, da 
4 etc...)

 4 etc...)
-- 
