Newsgroup: it.comp.lang.visual-basic
Titolo: 8milioni di operazioni, possibile ridurle?

Ciao a tutti,
Qualcuno di voi mi ricorderà...dopo diversi mesi senza scrivere niente in vb 
eccomi alle prese con un bel problema.
premetto di non essere un super esperto ma di riuscire comunque a scrivere 
qualcosa di funzionante in Vb.
Il mio problema è che questa volta quello che ho scritto funziona ma che 
impiega troppo tempo a fare quello che mi serve e sono convinto che esiste 
una soluzione più veloce che io ignoro ma che sicuramente qualcuno di voi 
conosce.
Cerco di spiegarvi meglio che posso.
Ho una tabella TOTALONE strutturata in questo modo
CodiceCliente, Articolo, MeseAcquisto
i record non sono univoci, ossia lo stesso codicecliente può essere ripetuto 
N volte così come gli altri campi. Esempio
10001, Art12, Gennaio05
10001, Art12, Febbraio05
10007, Art12, Gennaio05
10007, Art17, Marzo05
Questa tabella, in parole povere, contiene gli acquisti che i clienti hanno 
effettuato nei vari mesi.
Data una tabella ARTICOLI contenente 200 articoli differenti, e una tabella 
CLIENTI contenente 41.000 clienti
devo estrarre: quanti clienti hanno comprato un singolo articolo per 1 solo 
mese, per 2 mesi SUCCESSIVI, per 3 mesi SUCCESSIVI, per 4 mesi SUCCESSIVI 
etc. (per il momento ci sono solo i dati di gennaio, febbraio e marzo, 
quindi il massimo estraibili è 3 mesi successivi)
Per fare questo mi sono anche costruito una tabella Mesi contenente l'elenco 
dei mesi che a me servono (Gennaio05,Febbraio05,Marzo05)
Ho scritto una procedura che, tramite l'uso di tabelle temporanee, mi estrae 
quanto richiesto ma ci mette una infinità di tempo. L'ho avviata alle 4 di 
stanotte e dopo quasi 6 ore non è neanche al 50%
Vi riporto quello che ho scritto
(non vi riporto il codice perchè è ancora molto sporco, non l'ho ancora 
"ordinato" per la vista, ma vi scrivo il procedimento)
-----------------------------------------------------------------------------
Dim Mesi as Integer
Mesi=1
per ogni record di tb ARTICOLI
 per ogni record di tbClienti
  select * from TOTALONE dove CodiceCliente=rs.Tbclienti e 
Articolo=rs.TbArticoli
    Prendo il valore MeseAcquisto del recordset creato
      Per ogni mese in tbMesi,ripeti fino a quando tbMesi.EOF=True
        faccio una nuova select aggiungendo come condizione 
MeseAcquisto=MeseAcquisto+1
          se il recordset è popolato
            if non esiste nella tabella temporanea altro recordo con stesso 
CodiceCliente
              salvo in una tabella temporanea (tbTemp) i valori 
CodiceCliente, Mesi=Mesi+1
            else
              faccio update del record, impostando Mesi=Mesi+1 solo se il 
valore Mesi precedente era minore
            end if
          altrimenti
            if non esiste nella tabella temporanea altro recordo con stesso 
CodiceCliente
              salvo in una tabella temporanea (tbTemp) i valori 
CodiceCliente, Mesi=1
            else
              faccio update del record, impostando Mesi=Mesi+1 solo se il 
valore Mesi precedente era minore
           end if
         fine se
   Fine loop tb Mesi
 Fine Loop tbClienti
 Dalla tbTemp conto quanti record contengono Mesi=1, quanti Mesi=2 e quanti 
Mesi=3
 salvo i valori, insieme all'articolo, in un singolo record di una tabella 
tbFinale in modo da avere una singola riga
 per ogni articolo
 cancello la tbTemp
Loop tb Articoli, passo al prossimo articolo e ripeto tutto
-----------------------------------------------------------------------------
Alla fine mi dovrei trovare con una tbFinale con 200 record, ognuno dei 
quali conterrà quanto richiesto.
Il problema è, come dicevo, che questa procedura deve essere ripetuta 
200x41.000= 8milioni e 200mila volte.
e ovviamente ci vuole il suo tempo.
Quindi la mia domanda è, esiste un modo per velocizzare il tutto evitando 8 
milioni di calcoli (considerate che ogni mese che passerà quei 41.000 
clienti aumenteranno...)
Grazie a tutti quelli che cercheranno di aiutarmi!
ciao!
 

 CodiceCliente, Articolo, MeseAcquisto
Mi devi dire prima come sono strutturate le tabelle (campi, tipo, chiavi)
con particolare riguardo al totalone
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 SUCCESSIVI
[cut]
Non mi č chiarissimo cosa tu intenda ottenere.
Supponendo che tu voglia i clienti che hanno acquistato un solo codice 
articolo (anche in piů occorrenze), per 1, 2, 3, 4 mesi, puoi fare una cosa 
del genere (PS: queste cose si fanno in SQL, non certo in vb...):
SELECT CLIENTI.CLIENTE
    CONTEGGIO_1=COALESCE(ART_1_MESE.CONTEGGIO,0.0),
    CONTEGGIO_2=COALESCE(ART_2_MESI.CONTEGGIO,0.0),
    CONTEGGIO_3=COALESCE(ART_3_MESI.CONTEGGIO,0.0),
    CONTEGGIO_4=COALESCE(ART_4_MESI.CONTEGGIO,0.0)
FROM CLIENTI
LEFT OUTER JOIN
    (SELECT CODICECLIENTE,
        CONTEGGIO=COUNT(ARTICOLO)
            FROM (SELECT DISTINCT CODICECLIENTE, ARTICOLO
                        FROM TOTALONE
            WHERE MESEACQUISTO IN ('GENNAIO05')
                ) AS B
    GROUP BY B.CODICECLIENTE) AS ART_1_MESE
ON CLIENTI.CLIENTE=ART_1_MESE.CODICECLIENTE
LEFT OUTER JOIN
    (SELECT CODICECLIENTE,
        CONTEGGIO=COUNT(ARTICOLO)
            FROM (SELECT DISTINCT CODICECLIENTE, ARTICOLO
                        FROM TOTALONE
            WHERE MESEACQUISTO IN ('GENNAIO05', 'FEBBRAIO05')
                ) AS B
    GROUP BY B.CODICECLIENTE) AS ART_2_MESI
ON CLIENTI.CLIENTE=ART_2_MESI.CODICECLIENTE
LEFT OUTER JOIN
    (SELECT CODICECLIENTE,
        CONTEGGIO=COUNT(ARTICOLO)
            FROM (SELECT DISTINCT CODICECLIENTE, ARTICOLO
                        FROM TOTALONE
            WHERE MESEACQUISTO IN ('GENNAIO05', 'FEBBRAIO05','MARZO05')
                ) AS B
    GROUP BY B.CODICECLIENTE) AS ART_3_MESI
ON CLIENTI.CLIENTE=ART_3_MESI.CODICECLIENTE
LEFT OUTER JOIN
    (SELECT CODICECLIENTE,
        CONTEGGIO=COUNT(ARTICOLO)
            FROM (SELECT DISTINCT CODICECLIENTE, ARTICOLO
                        FROM TOTALONE
            WHERE MESEACQUISTO IN ('GENNAIO05', 
'FEBBRAIO05','MARZO05,'APRILE05')
                ) AS B
    GROUP BY B.CODICECLIENTE) AS ART_4_MESI
ON CLIENTI.CLIENTE=ART_4_MESI.CODICECLIENTE
Cosě ottieni un recordset con tutti i clienti e quanti articoli diversi 
hanno acquistato in 1,2,3 e 4 mesi.
Se vuoi filtrarli lato Sql, basta aggiungere un Where alla fine. Se vuoi 
filtrarli lato VB, puoi usare il filter del recordset (per 41.000 clienti, 
forse conviene filtrare lato Sql).
Ciao
Alberto
-- 
E tutto mi sembrava andasse bene... 

 chiavi) con particolare riguardo al totalone
TOTALONE:
ID -> Numerico (contatore), Indicizzato, Duplicati non ammessi, chiave 
primaria
CodiceCliente    -> Testo, Indicizzato, Duplicati amessi
Articolo    -> Testo, Indicizzato, Duplicati ammessi
MeseAcquisto -> Testo,Indicizzato,Duplicati ammessi
Categoria -> Testo
Prezzo -> Valuta
(da notare che se non indicizzavo quei campi i tempi erano 10 volte 
maggiori, faceva un operazione al secondo. La tabella totalone contiene 
circa 312.000 record)
ARTICOLI:
ID -> Numerico (contatore), Indicizzato, Duplicati non ammessi, chiave 
primaria
Articolo -> Testo, Indicizzato, Duplicati amessi
Categoria -> Testo
CLIENTI:
ID -> Numerico (contatore), Indicizzato, Duplicati non ammessi, chiave 
primaria
CodiceCliente -> Testo, Indicizzato, Duplicati non ammessiù
MESI:
ID -> Numerico (contatore), Indicizzato, Duplicati non ammessi, chiave 
primaria
Mese -> Testo
TEMP:
ID -> Numerico (contatore), Indicizzato, Duplicati non ammessi, chiave 
primaria
CodiceCliente -> Testo, Indicizzato, Duplicati amessi
Mesi -> Numerico
FINALE:
ID -> Numerico (contatore), Indicizzato, Duplicati non ammessi, chiave 
primaria
Articolo    -> Testo, Indicizzato, Duplicati amessi
Categoria -> Testo, Indicizzato, Duplicati amessi
1Mesi -> Numerico
2Mesi -> Numerico
3Mesi -> Numerico 

 Alberto
Grazie mille 

 La inserisco semplicemente in una maschera query?
Per testarla, sicuramente si.
Poi dovrai metterla nel source del recordset.


 e non ricordo se Access vuole AS per gli alias.
Lo so che approfitto della tua generosità, ma non è che potresti 
ripostarmela tu?
Io non so neanche da dove iniziare
Prometto però che finita sta cosa, visto che la dovrò rifare a fine giugno 
su sei mesi, mi compro un bel librone su SQL e me lo leggo tutto e inoltre 
mi installo sql-server
Se non puoi, non fa niente... mi "arrangerò" in qualche modo :-)
Grazie infinite per l'aiuto!

 giugno su sei mesi,
No, beh, se ogni due mesi devi cambiare la struttura, allora tanto vale 
ripensarla completamente e renderla dinamica.
Pensavo che i 4 mesi fossero un parametro fisso.


  
bye
r

 tutto e inoltre mi installo sql-server
BLA BLA BLA BLA BLA BLA BLA BLA
scusami ma te lo meriti eh!
fai una ricerca nel ng di quanti han fatto il coccodrillo!
"Ragazzi prometto che poi studio...mi informo...leggo...spippolo....compro
la licenza...leggo la guida...etc etc etc"
Inoltre:
auguri per la conversione in access!!!....
clicca su query e incolla in "sql" il "mostro" di Albe....
poi comicia a documentarti/debuggare  ogni incazzatura di access (e ce ne
saranno o se ce ne saranno) !

 ce ne saranno o se ce ne saranno) !
Non posso dire che avete torto
Allora per il momento mi tengo le mie 12 ore di elaborazione (ha finito 
proprio adesso)
Domani mi cerco un libro e inizio ad imparare in modo da essere pronto a 
riscriverla per fine giugno
Avete qualche titolo da consigliarmi che faccia al caso mio?
Almeno questo ditemelo... :-) 

A<