Query innestata | SQL & MySQL

Topic: Pubblico - Composto da 10 Posts di 2 Utenti.

07 Giugno, 2010 09:01 #1
avcom
Utente

avcom
Registrato: Jun, 2010
Posts: 12
Offline

Salve a tutti. Ho un problema nei tempi di risposta di una query che ho strutturato, immagino a causa del numero di operazioni di confronto che compie, aggravata dal numero di istanze che deve valutare.

Vi riassumo la situazione, premettendo che utilizzo un motore MyIsam, che non consente referenziazione esterna:

Ho due tabelle, una con l’anagrafica degli utenti, l’altra con lo storico delle operazioni che essi hanno compiuto (unita alla prima con il campo IDUSER che riporta l’ID dell’utente).

Quando eseguo una ricerca vengono interrogate entrambi le tabelle. La mia ricerca, oltre a cercare tra i dati anagrafici degli utenti (Es.: cognome =”Rossi”, città=”Roma”) dovrebbe filtrare ulteriormente a seconda dell’esito dell’ULTIMA (e solo di questa) operazione.

Faccio l’esempio di un caso. Se l’utente ha ricevuto una telefonata e ha dato una risposta negativa in data 01/01/2010, e lo stesso utente ha poi dato risposta positiva il 02/02/2010, effettuando una ricerca per ottenere gli utenti che hanno dato esito negativo nel periodo dal 01/01/2010 al 03/03/2010, l’utente di cui sopra non dovrebbe figurare, dato che l’esito positivo rilasciato successivamente (essendo l’ultimo) dovrebbe “sovrascrivere” quello negativo rilasciato in precedenza.

Svolgendo queste operazioni tra MySQL e codice di programmazione, i tempi di risposta erano decisamente lenti, e sarebbero cresciuti con l’aumentare delle istanze delle tabelle. Suppongo quindi che abbia bisogno di query innestate ma non so come strutturarle.

Chiedo aiuto ad utenti esperti o che abbiano già avuto problematiche simili. Ringrazio in anticipo

07 Giugno, 2010 18:54 #2
g2d
Moderatore

g2d
Registrato: Jul, 2008
Posts: 867
Offline
Segui g2d su Twitter!

Ciao avcom

Per prima cosa menvenuto su MySQL Italia

Beh le cose che si possono fare per risolvere il tuo problema sono veramente molte.

Se non è un problema postaci la query che ci lavoriamo assieme.

Ti dò subito un pò di dritte … Come sei messo con gli indici? Di quanti dati stai parlando ?

Facci sapere, migliorare l’esecuzione di una query è sempre un cosa molto stimolante

Saluti algweb


Un tempo ero algweb ora sono g2d

11 Giugno, 2010 07:37 #3
avcom
Utente

avcom
Registrato: Jun, 2010
Posts: 12
Offline

tabella_utenti id, nome, cognome

tabella_operazioni id, idutente, data_operazione, esito_operazione

Questa è la struttura delle mie tabelle. Il problema, come postato in precedenza, è filtrare la ricerca secondo l’ultima operazione eseguita.

Select tabella_utenti.*, tabella_operazioni.data_operazione from tabella_utenti Inner join tabella_operazioni on (tabella_utenti.id=tabella_operazioni.idutente) where tabella_utente.cognome=’Rossi’ and (ULTIMA OPERAZIONE FATTA == ok)

Il mio blocco sta proprio nel dire in sql come restituirmi l’utente se il suo ultimo stato risulta essere OK

In attesa di una Vs. anticipatamente grazieee

11 Giugno, 2010 18:58 #4
g2d
Moderatore

g2d
Registrato: Jul, 2008
Posts: 867
Offline
Segui g2d su Twitter!

Ciao avcom

Bentornato su MySQL Italia

Bene, l’importante è capirsi, tranquillo.

Il tuo problema va risolto con ORDER BY data_operazione DESC LIMIT 1

Riscrivo la tua query per essere più chiaro

1Select tabella_utenti.*, tabella_operazioni.data_operazione from tabella_utenti Inner join tabella_operazioni on (tabella_utenti.id=tabella_operazioni.idutente) where tabella_utente.cognome=Rossi and 
2(esito_operazione == ok) ORDER BY data_operazione  DESC LIMIT 1

Tutto chiaro ?

Facci sapere

Saluti algweb


Un tempo ero algweb ora sono g2d

14 Giugno, 2010 07:27 #5
avcom
Utente

avcom
Registrato: Jun, 2010
Posts: 12
Offline

Grazie per la dedizione al mio problema caro Algweb, ma come hai detto tu l’importante è capirsi…quindi mi sa che non ci siamo capiti, ovviamente sono stato poco chiaro io. Il problema fondamentale sta nel fatto che, eseguendo la query così come l’hai riscritta tu, otterrei solo i risultati con esito = OK. A me invece serve sapere se dopo la data di quell’esito, per lo stesso utente, sia stata effettuata un’altra operazione, il cui esito “nasconde” il precedente esito ok. Riepilogo l’esempio: Se interrogo il database per verificare gli esiti negativi nel periodo di febbraio 2009, la query deve riportarmi tutti gli utenti che hanno dato esito negativo del suddetto periodo, escludendo però quelli che dopo febbraio 2009 sono stati ricontattati e quindi hanno avuto una nuova operazione con un nuovo esito.

Essendo ancora più pratico: ho queste operazioni effettuate Mario Rossi 22/01/2009 NEGATIVO Carlo Bianchi 03/02/2009 NEGATIVO Franco Verdi 05/02/2009 OK Piero Bruni 06/02/2009 NEGATIVO Giorgio Neri 12/02/2009 OK Mario Rossi 15/03/2009 OK

eseguendo la query per trovare gli esiti negativi da gennaio 2009 a febbraio 2009 devono risultarmi Carlo Bianchi e Piero Bruni, ma non Mario Rossi dato che l’esito di marzo “sovrascrive” o “nasconde” l’esito negativo rilasciato a gennaio.

Ricordo che l’anagrafica utente e lo storico operazioni sono memorizzate in tebelle diverse e che oltre a effettuare ricerca sugli esiti potrei filtrare ulteriormente su altri dati sempre contenuti nelle tue tabelle, come città, operatore, etc etc.

Grazie ancora per la disponibilità, confido in un vostro sugegrimento.

14 Giugno, 2010 07:31 #6
avcom
Utente

avcom
Registrato: Jun, 2010
Posts: 12
Offline

riscrivo i dati perchè la pubblicazione del post ha cancellato gli “a capo” e sembra meno chiaro. Mario Rossi 22/01/2009 NEGATIVO. Carlo Bianchi 03/02/2009 NEGATIVO. Franco Verdi 05/02/2009 OK. Piero Bruni 06/02/2009 NEGATIVO. Giorgio Neri 12/02/2009 OK. Mario Rossi 15/03/2009 OK.

eseguendo la query per trovare gli esiti negativi da gennaio 2009 a febbraio 2009 devono risultarmi Carlo Bianchi e Piero Bruni, ma non Mario Rossi dato che l’esito di marzo “sovrascrive” o “nasconde” l’esito negativo rilasciato a gennaio.

Grazie

14 Giugno, 2010 07:33 #7
avcom
Utente

avcom
Registrato: Jun, 2010
Posts: 12
Offline

Sorry, mi sa che nn ci riesco a renderli + chiari, riprovo Mario Rossi 22/01/2009 NEGATIVO.

Carlo Bianchi 03/02/2009 NEGATIVO.

Franco Verdi 05/02/2009 OK.

Piero Bruni 06/02/2009 NEGATIVO.

Giorgio Neri 12/02/2009 OK.

Mario Rossi 15/03/2009 OK.

14 Giugno, 2010 20:45 #8
g2d
Moderatore

g2d
Registrato: Jul, 2008
Posts: 867
Offline
Segui g2d su Twitter!

Ciao avcom

penso di riuscirti ad aiutare, però mi devi far capire bene il risultato che vuoi ottenere.

Mi spiego meglio, dalla tabella che hai postato, quale deve essere il risultato? saresti così gentile da postare anche il risultato che vuoi ottenere?

Non disperare che riusciamo a farcela!

Saluti algweb


Un tempo ero algweb ora sono g2d

16 Giugno, 2010 07:38 #9
avcom
Utente

avcom
Registrato: Jun, 2010
Posts: 12
Offline

Ciao algweb, questo è quello che avevo scritto in precedenza:

Mario Rossi 22/01/2009 NEGATIVO.

Carlo Bianchi 03/02/2009 NEGATIVO.

Franco Verdi 05/02/2009 OK.

Piero Bruni 06/02/2009 NEGATIVO.

Giorgio Neri 12/02/2009 OK.

Mario Rossi 15/03/2009 OK.

eseguendo la query per trovare gli esiti negativi da gennaio 2009 a febbraio 2009 devono risultarmi Carlo Bianchi e Piero Bruni, ma non Mario Rossi dato che l’esito di marzo “sovrascrive” o “nasconde” l’esito negativo rilasciato a gennaio.

Faccio un altro esempio:

Mario Rossi 01/01/2009 NEGATIVO.

Carlo Bianchi 03/01/2009 NEGATIVO.

Piero Bruni 06/01/2009 NEGATIVO.

Mario Rossi 15/02/2009 OK.

Carlo Bianchi 18/02/2009 OK.

Piero Bruni 26/02/2009 OK.

eseguendo la query per trovare gli esiti negativi da gennaio 2009 a febbraio 2009 non devo ottenere risultati dato che tutti gli esiti “OK” postumi annullano di fatto gli esiti negativi.

Semplicemente voglio ottenere una ricerca che tenga conto solo dell’esito + recente. Ossia che dopo aver verificato la condizione base (se l’esito è negativo nel dato periodo) indaghi sui risultati per verificare che non ci sia un ulteriore esito che sovrascriva quello ritornato per quell’utente.

Ripeto che all’inizio svolgevo questa indagine tramite codice di programmazione, effettuando un ciclo sui risultati ottenuti dalla query, verificando che non ci fossero altri esiti successivi relativi agli utenti ritornati. L’inconveniente è che al crescere del numero di utenti aumentano eccessivamente i tempi di risposta. In base a questo volevo riuscire ad ottenere tutto con un unica query, evitando così il ciclo sui risultati.

In poche parole devo filtrare sui risultati della query, tenendo conto solo di quelli che sono gli ultimi esiti in ordine cronologico.

Spero di essere stato più chiaro grazie ancora

16 Giugno, 2010 22:03 #10
g2d
Moderatore

g2d
Registrato: Jul, 2008
Posts: 867
Offline
Segui g2d su Twitter!

Ciao avcom

tranquillo tranquillo che non ti abbandono, scusami se ti ho fatto aspettare ma oltre a capire bene volevo fare qualche test.

Penso di aver trovato la tua soluzione, confesso che non è stato facile, penso che forse non sia la query più performante che si possa fare in assoluto però…... vediamo come va…. in ogni caso se è lenta co lavoriamo per migliorarla

1SELECT nome FROM tabella WHERE 
2(data >'2010-01-1'AND data < '2010-02-28') 
3AND esito='NEG' AND nome NOT IN (
4SELECT NOME FROM tabella WHERE esito='POS' AND data > '2010-01-1')

Che ne pensi ?

Fammi sapere

Saluti algweb


Un tempo ero algweb ora sono g2d

Condividi su:

Loggati o Registrati per replicare