Pagina 1 di 4 1 2 3 ... ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 32
  1. #1

    [MySQL] Problema composizione query

    Ciao a tutti,

    nel mio database ho 2 tabelle: "persone" e "chiamate". In "persone" c'è un attributo "ID"(chiave primaria) che identifica ogni persona ed invece in "chiamate" c'è il campo "ID"(chiave primaria) che identifica ogni chiamata a cui è associato l'ID(chiave esterna) di una persona. In pratica in "chiamate" sono salvate tutte le chiamate che sono state fatte ad una certa persona riportandone anche la data, quindi l'ID della chiamata cambierà sempre ed invece l'ID delle persona potrà comparire su più record(quando si fanno più chiamate alla stessa persona!!).

    Il mio problema sorge quando voglio fare una query che mi ritorni i dati della persona e delle chiamate ma solo per le ultime chiamate fatte. Faccio un esempio per far capire meglio:

    Tab "persone"
    ID|Nome|Cognome
    1|mario|rossi
    2|luigi|verdi
    3|giorgio|blu

    Tab "chiamate"
    ID|ID_persona|datachiamata|rispostaallachiamata
    1|1|10/01/2010|interessato
    2|3|10/01/2010|ok
    3|2|15/01/2010|niente
    4|2|03/01/2010|va bene
    5|3|25/01/2010|risentire
    6|3|09/01/2010|non interessato

    Risultato della query:

    Nome|Cognome|datachiamata|rispostaallachiamata
    mario|rossi|10/01/2010|interessato
    luigi|verdi|15/01/2010|niente
    giorgio|blu|25/01/2010|risentire

    Non so se mi sono spiegato bene comunque questo è il mio problema.

    Qualcuno può aiutarmi?

    Grazie

  2. #2
    Utente di HTML.it L'avatar di nicola75ss
    Registrato dal
    Nov 2004
    Messaggi
    12,923
    codice:
    select p.nome,p.cognome,tab2.datachiamata,tab2.rispostaallachiamata
    from
    (select concat(id_persona,max(datachiamata)) as ultima from chiamate
    group by id_persona) as tab1
    left join chiamate as tab2 ON tab1.ultima = concat(tab2.id_persona,tab2.datachiamata)
    inner join persone as p on tab2.id_persona = p.id

  3. #3
    Grazie mille!!!

  4. #4
    Scusa ma mi sono accorto di un problema.
    Se una persona non ha nessuna chiamata associata io vorrei che mi ritornasse lo stesso il nome e il cognome di questa persona.
    Come potrei risolvere?

    Grazie

  5. #5
    Utente di HTML.it L'avatar di nicola75ss
    Registrato dal
    Nov 2004
    Messaggi
    12,923
    Semplicemente metti in relazione tramite left join la tabella persone con tutto il resto.

    codice:
    select p.nome,p.cognome,tab3.datachiamata,tab3.rispostaallachiamata 
    from persone as p
    left join (
    select * 
    from 
    (select concat(id_persona,max(datachiamata)) as ultima from chiamate
    group by id_persona) as tab1
    left join chiamate as tab2 
    on tab1.ultima = concat(tab2.id_persona,tab2.datachiamata)) as tab3
    on p.id = tab3.id_persona

  6. #6
    Perfetto!!! Grazie!!! Quindi niente inner join finale ma un left join prima di fare tra tab3 e persone

  7. #7
    Ciao, scusa se rompo ancora; la query fa esattamente quello che volevo però è molto lenta nell'esecuzione visto che nella tab chiamate ho più di 20000 record e in persone più di 10000. Non si riesce ad ottimizzarla in qualche modo per renderla più veloce!?

    Grazie

  8. #8
    Utente di HTML.it L'avatar di nicola75ss
    Registrato dal
    Nov 2004
    Messaggi
    12,923
    Posta l'output di

    show create table persone

    show create table chiamate

    e di

    codice:
    explain select p.nome,p.cognome,tab3.datachiamata,tab3.rispostaallachiamata 
    from persone as p
    left join (
    select * 
    from 
    (select concat(id_persona,max(datachiamata)) as ultima from chiamate
    group by id_persona) as tab1
    left join chiamate as tab2 
    on tab1.ultima = concat(tab2.id_persona,tab2.datachiamata)) as tab3
    on p.id = tab3.id_persona

  9. #9
    show create table persone:
    'CREATE TABLE `persone` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `nome` varchar(45) NOT NULL,
    `cognome` varchar(45) NOT NULL,
    PRIMARY KEY (`id`),
    ) ENGINE=InnoDB AUTO_INCREMENT=30029 DEFAULT CHARSET=latin1'

    show create table chiamate:
    'CREATE TABLE `chiamate` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `id_persona` int(11) NOT NULL,
    `datachiamata` date DEFAULT NULL,
    `rispostaallachiamata` varchar(300) DEFAULT NULL,
    PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=40440 DEFAULT CHARSET=latin1'

    e di

    codice:
    explain select p.nome,p.cognome,tab3.datachiamata,tab3.rispostaallachiamata 
    from persone as p
    left join (
    select * 
    from 
    (select concat(id_persona,max(datachiamata)) as ultima from chiamate
    group by id_persona) as tab1
    left join chiamate as tab2 
    on tab1.ultima = concat(tab2.id_persona,tab2.datachiamata)) as tab3
    on p.id = tab3.id_persona
    Risultato:

    id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra
    1, 'PRIMARY', 'p', 'ALL', '', '', '', '', 15062, ''
    1, 'PRIMARY', '<derived2>', 'ALL', '', '', '', '', 9445, ''
    2, 'DERIVED', '<derived3>', 'ALL', '', '', '', '', 9233, ''
    2, 'DERIVED', 'tab2', 'ALL', '', '', '', '', 23619, ''
    3, 'DERIVED', 'chiamate', 'ALL', '', '', '', '', 23619, 'Using temporary; Using filesort'

  10. #10
    Utente di HTML.it L'avatar di nicola75ss
    Registrato dal
    Nov 2004
    Messaggi
    12,923
    Prova ad aggiungere un indice alla tabella chiamate

    alter table chiamate add index(id_persona,datachiamata);

    e vedi se riscontri dei miglioramenti.

    Eventualmente, se non fai uso di chiavi esterne e di transazioni, modifica l'engine delle tabelle da innodb a myisam.

    alter table persone engine=myisam;
    alter table chiamate engine=myisam;

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.