Newsgroup: it.comp.lang.visual-basic
Titolo: Query un po' più difficile...

Ragazzi avrei bisogno di una query un po' più complicata...
Ho una tabella con un elenco di telefonate effettuate.
Per ogni singola telefonata c'è il numero chiamato, la data e ora in cui 
è partita la telefonata, e la durata (espressa in secondi).
Come posso fare per sapere in che data e ora la somma del campo [durata] 
ha superato un certo limite (diciamo 100 ore, cioè 6.000 minuti, cioè 
360.000 secondi)? O magari anche l'ID del record associato a quel limite.
Cioè se scandendo la tabella (ordinata per data/ora di chiamata) giungo 
a un determinato gg/mm/aaaa, come faccio a ricavarmi l'ID del record in 
cui ho raggiunto il limite?
-- 
Rivolterò il mondo per trovarlo, e anche se andasse in Indocina uno dei 
nostri starà nascosto in una ciotola di riso pronto a sparargli nel culo.
(Pulp Fiction)


Ciao,
prima di dare una risoposta che non serve a nulla vorrei una conferma:
mettiamo che il limite si 3500,tu hai questi dati
Id       Data                            Durata
-----  ----------------------   --------
100   26/05/2004 08:00:15    1000
101   26/05/2004 12:00:15    1400
102   26/05/2004 15:00:30    1200
103   27/05/2004 09:15:15    1100
104   27/05/2004 12:35:16    1200
105   27/05/2004 15:18:30    1300
Calcolando il progressivo
Id       Data                            Durata    Progr
-----  ----------------------   --------  ---------
100   26/05/2004 08:00:15    1000      1000
101   26/05/2004 12:00:15    1400      2400
102   26/05/2004 15:00:30    1200      3600
103   27/05/2004 09:15:15    1100      1100
104   27/05/2004 12:35:16    1200      2300
105   27/05/2004 15:18:30    1300      3600
La query dovrebbe restituirti gli ID 102 e 105
Giusto ?
Ciao Giorgio

 
Secondo me andando in ordine il limite viene superato col terzo record e 
quindi gli id da restituire sono i primi 2, 100 e 101.
Credo che Darkbyte voglia calcolare il superamento di una soglia che, ad 
esempio, potrebbe servire per valutare quando scatta uno sconto sulla 
tariffa o qualcosa di simile.
ciao
	maxx
-- 
NOSPAM: Rimuovere i trattini dallo username!
Cut hyphens from my username!


bo, c'è anche da dire che in una giornata le ore sono 24 quindi il
progressivo non è da calcolare nel giorno ma se gli interni sono tanti ?
Forse è meglio che ci fa un esempio.
ciao Giorgio

 tariffa o qualcosa di simile.
Scusate se rispondo solo ora ma non ho avuto modo di toccare il pc.
Allora stando a quella tabella io vorrei semplicemente ottenere ID=102, 
cioè il record in cui sono arrivato a 3500 o l'ho superato.
Cioè per me l'importante è sapere quando è stata superata la soglia.
Poi da lì in poi devo contare quante telefonate sono state fatte e il 
tempo complessivo... ma una volta che so l'ID posso tranquillamente 
ricavarmi data e ora e riorganizzare la query per sapere altro...


 
Ho titrato fuori sta roba e' da adattaare, ma il principio potrebbe 
essere quello giusto. Ho dovuto fare una supposizione, e cioe' che gli 
id siano ordinati con il campo data, cioe' il record con id=100 
identifica sempre un record con data inferiore al record con id=101.
select last(idrecord) from
(SELECT 
chiamate.id
 as idrecord
FROM chiamate
where (select sum(c.durata) from chiamate as c where 
c.id
 < 
chiamate.id
) 
<500
order by 
chiamate.id
)
Adesso sono troppo stanco, ma penso si possa modificare facilmente per 
usare la data come campo secondo cui ordinare...


 progressivo non è da calcolare nel giorno ma se gli interni sono tanti ?
Ma ordinando per data crescente e, a parità di data, per ora crescente, 
si ottengono voci ben distinte fra loro.
Al massimo possono risultare telefonate alla stessa data e alla stessa 
ora (si tratta di un callcenter quindi essendoci 20 operatori possono 
anche partire telefonate contemporaneamente), ma la cosa non è rilevante 
in quanto il mio compito è solo quello di sapere in che data (e a che 
ora) è stata varcato un certo numero di ore di conversazione. Quindi se 
anche succedesse qualcosa di questo tipo:
Id       Data      ORA       Durata    Progr
-----  --------- --------   --------  ---------
100   25/05/2004 08:00:15    1000      1000
101   26/05/2004 13:01:20    1400      2400
102   26/05/2004 12:00:15    1200      3600
102   26/05/2004 12:00:15    1200      4800
103   27/05/2004 09:15:15    1100      9900
104   27/05/2004 12:35:16    1200     11100
105   27/05/2004 15:18:30    1300     12400
in cui è presente due volte il 26/05/2004 con 12:00:15 a me non cambia 
nulla: in ogni caso con una delle due telefonate è stata varcata la 
soglia, ed è inutile decidere quale delle due.
Tanto la differenza sarà di pochi secondi (roba di minuti al massimo), 
ma in un mese potrò perdere un solo minuto per quella questione della 
soglia, e non mi interessa.
Una volta che so qual'è il primo ID oltre il quale le ore non sono più 
nella soglia, posso indicare all'utente che si trova al pc la data in 
cui le ore si sono consumate e calcolare da quel punto in poi il numero 
di telefonate effettuate e la durata complessiva.
L'importante, ripeto, è sapere che (vedi tabella di sopra) ID=102, 
perchè ho superato 3500.


 ha scritto
nel messaggio news:8eNtc.78121$Qc.31...@twister1.libero.it...

Ciao,
a prescindere che ID dovrebbe essere univoco
con questa query ottieni il progressivo
--------------------------------------
Select T1.Id,
             T1.Data,
             T1.Durata,
             (SELECT SUM(Durata)
              FROM Tabella T2
             WHERE T1.Data>=T2.Data
                  AND T1.Id>=T2.Id) AS Progressivo
       FROM Tabella T1
Order By T1.Data,T1.id
--------------------------------------
ovvero questo risultato
-------------------------------------
Id Data Durata Progressivo
100 26/05/2004 8.00.15 1000 1000
101 26/05/2004 12.00.15 1400 2400
102 26/05/2004 15.00.30 1200 3600
103 27/05/2004 8.40.15 1100 4700
104 27/05/2004 8.40.15 1100 5800
105 27/05/2004 12.35.15 1200 7000
106 27/05/2004 15.20.30 1300 8300
---------------------------------------
il secondo passo è piu semplice basta selezionare la prima riga che supera
la tua soglia dalla query precedente ordinandola per progressivo
-----------------------------
SELECT TOP 1 *
FROM (Select  TOP 100 PERCENT
                        T1.Id,
                        T1.Data,
                       T1.Durata,
                      (SELECT SUM(Durata)
                       FROM Tabella T2
                       WHERE T1.Data>=T2.Data
                          AND T1.Id>=T2.Id) AS Progressivo
                FROM Tabella T1
               Order By T1.Data,T1.id)
WHERE Progressivo>5000
ORDER BY Progressivo
---------------------------------------
(La clausola TOP 100 PERCENT è necessaria nelle tabelle derivate in cui
viene usata la ORDER BY, Jet non da errore ma va in Crash)
Risultato
---------------------------------------
Id Data Durata Progressivo
104 27/05/2004 8.40.15 1100 5800
--------------------------------------
Ciao Giorgio

 nel messaggio news:8eNtc.78121$Qc.31...@twister1.libero.it...
ho dimanticato l'alias
--------------------
SELECT TOP 1 *
FROM (Select  TOP 100 PERCENT
                        T1.Id,
                        T1.Data,
                       T1.Durata,
                      (SELECT SUM(Durata)
                       FROM Tabella T2
                       WHERE T1.Data>=T2.Data
                          AND T1.Id>=T2.Id) AS Progressivo
                FROM Tabella T1
               Order By T1.Data,T1.id) AS T3
WHERE Progressivo>5000
ORDER BY Progressivo
---------------------
notte
Giorgio

Allora, vi ringrazio per il suggerimento.
Di funzionare funziona, ma ci mette un bel po' prima di fare il calcolo 
su 9200 record (e sono pochissimi ancora, perchè ho solo le telefonate 
di 3 giorni mentre il calcolo andrà eseguito sul mese intero).
Avevo pensato a qualcosa per ottimizzare il calcolo:
Inserisco in una tabella temporanea (Temp) tutte le telefonate con la 
relativa durata, ordinate per iniziotelefonata crescente, e ci aggiungo 
un campo Progr che conterrà di volta in volta la somma delle durate 
precedenti.
Ho scritto quindi questa query:
UPDATE Temp T1
    SET Progr=Durata+
    (SELECT T2.Durata FROM Temp T2 WHERE 
T2.ID
=T1.ID-1)
ma quando provo a lanciarla (da Access) mi compare una messagebox con su 
scritto:
'Per l'operazione è necessaria una query aggiornabile'
Che significa? Come risolvo?



Ciao,
Prova a modificare la query in questo modo
----------------------------------
SELECT TOP 1 *
FROM (
             SELECT T1.Id,
                   T1.Data,
                   T1.Durata,SUM(T2.Durata) AS Progressivo
             FROM Tabella AS T1 INNER JOIN
                   Tabella AS T2
                   ON Format(T1.Data,'yyyymmdd hh:mm:ss') &
Format(T1.Id,'0000000000')>=
                          Format(T2.Data,'yyyymmdd hh:mm:ss') &
Format(T2.Id,'0000000000')
            GROUP BY T1.Id,T1.Data,T1.Durata
           ORDER BY T1.Data, T1.id) T3
WHERE Progressivo>5000
ORDER BY Progressivo
------------------------------
usando una tabella derivata al posto di una Subquery dovrebbe essere più
veloce.
la sintassi per una query di aggiornamento è questa ma non vedo come possa
crearti un progressivo.
------------------------
UPDATE Temp T1  INNER JOIN Temp AS T2
                ON 
T2.ID
 = T1.ID-1
SET T1.Progr = [T1].[Durata]+[T2].[Durata];
-------------------------
Ciao Giorgio

 Ciao Giorgio
Ti ringrazio ancora per i suggerimenti, la modifica alla query la farò 
appena possibile (stasera credo, o domattina).
Per quanto riguarda questa seconda risposta intendevo dire che, andando 
a naso sulla prima query che mi suggeristi, ho pensato una cosa:
Select T1.Id,
              T1.Data,
              T1.Durata,
              (SELECT SUM(Durata)
               FROM Tabella T2
              WHERE T1.Data>=T2.Data
                   AND T1.Id>=T2.Id) AS Progressivo
        FROM Tabella T1
Order By T1.Data,T1.id
Cioè a quanto pare la subquery viene eseguita tante volte quanti sono i 
record scanditi dalla query principale... un po' come se fossero due 
cicli for annidati.
Su questa cosa m'è venuta un'idea, e cioè: SE quello che ho pensato è 
corretto, allora perchè non sfruttare il progressivo generato 
all'iterazione precedente per sommarlo al campo DURATA del record corrente?
Quindi volevo aggiornare il progressivo sommandogli il campo durata più 
il progressivo associato a id-1:
update t1
    set t1.progr=t1.durata +
    (SELECT t2.progr from temp t2 where 
t2.id
=t1.id-1)
ma così non va... però l'idea è quella: per ogni record di t1, sommo 
l'attuale durata + il progressivo generato all'iterazione precedente, e 
sfrutto il campo id che è sequenziale...
Ora provo con la query che mi hai suggerito con l'inner join...
Intanto attendo smentite sul mio ragionamento


 ha scritto nel messaggio
news:40bb...@x-privat.org...

Ciao, l'interazione precedente non esiste in un'istruzione SQL, i record non
vengono scritti uno alla volta ad ogni ciclo, se partiamo da una tabella con
il campo progr=0 questo avrà sempre il valore  uguale a 0 finchè la query
non termina e aggiorna la tabella con una sola scrittura.
Ciao Giorgio

 news:40bb...@x-privat.org...
dimenticavo....
per quanto riguarda il messaggio 'Per l'operazione č necessaria una query
aggiornabile' Access non accetta subquery o funzioni di aggregazione SUM MIN
MAX ecc nelle query di aggiornamento (č una chiavica ma č fatto cosě),
l'unico modo per fargliele digerire č utilizzare le funzioni esterne Dsum
Dmax Dmin ecc.
DSUM("CAMPO","TABELLA","CONDIZIONE")
--------------------
update t1
  set t1.progr=Nz(DSum("Durata","t1","Id<=" & t1.Id),0)
From T1
--------------------
Ciao Giorgio

Ok, ti ringrazio ancora una volta!!!
Ho provato a ristrutturare la query con l'inner join ed effettivamente 
funziona. Solo che il primo record non viene aggiornato in quanto non ha 
elementi che lo precedano.
Ma non mi interessa, perchè tanto so che non sarà mai la prima 
telefonata a farmi varcare il limite.
Comunque proverò la soluzione di qualche post fa, della tabella derivata.
Posterò appena possibile per dirti com'è andata!!!
