Newsgroup: it.comp.os.linux.sys
Titolo: [OT] MySQL e group by al contrario

Scrivo di quï¿œ la domanda che ho fatto su ics.database senza successo.
Ho una tabella anagrafica, in cui posso solo inserire dati senza
modificare quelli presenti.
Supponiamo di avere una anagrafica associata a Gandalf.
Al primo inserimento, ci sarï¿œ un solo record di Gandalf.
Al primo update, farï¿œ un nuovo inserimento ed avrï¿œ quindi
due record.
Il record corretto, con i dati validi, sarï¿œ sempre l'ultimo inserito
in ordine temporale. (c'ï¿œ anche n campo timestamp che mi salva la data
di inserimento).
Per avere i dati aggiornati di gandalf mi basterebbe fare:
select * from anagrafica where nome = 'gandalf'
    order by inserimento desc limit 1
A lungo andare questo metodo potrebbe portare ad errori.
La soluzione, a mio avviso, sarebbe creare una vista con una query
del tipo:
select * from anagrafica group by nome
il problema ï¿œ che la group by ragiona 'sequenzialmente', ovvero il primo
dato che trova diventa quello 'effettivo' del raggruppamento e per forza
di cose ï¿œ quello errato, ovvero il piï¿œ vecchio.
Come si puï¿œ fare a creare un group by al contrario, ovvero il record
raggruppato dovrebbe essere l'ultimo e non il primo ?
In pratica, vorrei avere una vista con un singolo record per ogni nome
e tale record deve essere l'ultimo inserito nella tabella anagrafica.
Idee?

 raggruppato dovrebbe essere l'ultimo e non il primo ?
suppendo che tu abbia un campo id come chiave primaria:
select * from anagrafica where id=(select id from anagrafica order by
inserimento desc limit 1) group by nome

 inserimento desc limit 1) group by nome
Ho provato, ma vien fuori un problema.
Mi prende un solo record, e non un solo record per ciascun nome.
La tabella �:
id;nome;valore;inserimento
3;ciccio;valore;1
2;gandalf;valore nuovo;2
1;gandalf;valore vecchio;1
mi prende solo il valore nuovo di gandalf, ciccio
non compare.

 e tale record deve essere l'ultimo inserito nella tabella anagrafica.
Quello che ti serve e' una select che ti restituisca l'elenco di tutte le 
righe piu' recenti, una per nome. Dopodiche' crei una vista da quella.
select * from anagrafica e where inserimento >= ALL (select inserimento from 
anag i where i.nome=e.nome);
create MyRecentView as select * from anagrafica e where inserimento >= ALL 
(select inserimento from anag i where i.nome=e.nome);
Probabilmente c'e' un modo piu' efficiente di formulare la prima query, 
questo e' il primo che mi e' venuto in mento.

 (select inserimento from anag i where i.nome=e.nome);
Per la vista nessun problema, poi me la creo a modo.
Intanto grazie.

 Probabilmente c'e' un modo piu' efficiente di formulare la prima query, 
Ho visto che si puï¿œ impostare l'order by implicito di una tabella
direttamente in fase di creazione della tabella.
Potrei impostare un ordinamento desc ed almeno in teoria basterebbe
fare un semplice group by. Essendo ordinato in desc, il primo record
che il group by mostrerebbe sarebbe automaticamente l'ultimo inserito.
Ma cosï¿œ facendo si che questo metodo porterebbe ad errori, sfido a
ricordarsi di come ragiona una tabella sotto-banco tra 6 mesi, quando
fa l'opposto di quello che dovrebbe fare con una query tradizionale.
In pratica una select mostrerebbe i dati al contrario, tra 6 mesi
solo mandrake capirebbe il perchï¿œ senza rompersi la testa.

 Idee?
Da come ho capito il problema,
SELECT campo1, campo2, campo3, max(campo4)
FROM tabella
GROUP BY campo4
Dove campo4 riporta il timestamp dell'ultimo inserimento del record.
Tieni comunque presente che io gestirei la cosa in un altro modo, ovvero
aggiungerei un campo sulla tabella che mi permetta di invalidare il
record e andrei in update su quel campo ogni volta che aggiorno i dati
del record (per l'aggiornamento di tale campo, se proprio non ti e`
possibile via interfaccia, utilizzerei un trigger)
Enrico

 Idee?
Una query con una subquery:
La sub query fa qualcosa come ' select nome, MAX (time) as time from anagcli
group by nome ', la query aggancia in join la sub query usando nella parte
ON della join i campi ritornati dalla sub query.
Una ricerca con google ti da i dettagli sulle subquery, tieni conto che non
tutti i motori dei database implementano le stesse possibilità d'uso delle
subquery, nel caso che non ci fosse una certa modalità d'uso, diventa
obbligatorio passare per un view o per una tabella temporanea.
In quanto al metodo da te proposto tieni conto che supporre che i campi non
esplicitamente elaborati da un singolo raggruppamento siano per forza
appartenenti allo stesso record è un errore molto grosso, perché non c'è
nessuna garanzia di ciò, e tutto dipende dal motore del database.
In sintesi se avessi anche un campo time2 su cui fare '''il
group/selezione''' deve essere fatto con una seconda sub query che elabori
il risultato della prima subquery (che naturalmente non restituirà solo
nome ma anche time2 (per esempio select nome, time2, MAX (time) as
time ...)).
In sintesi l'unico modo sicuro di eseguire quello che hai chiesto è di
elabora un raggrupamento/selezione di un campo alla volta (nel tuo caso non
c'è problema, visto che hai solo un campo da elaborare).

 nella parte ON della join i campi ritornati dalla sub query.
]zac[
Se ti sembra troppo contorno posso postare un esempio concreto.