Newsgroup: it.comp.appl.access
Titolo: analitico giorni

ho la tabella T1 con i campi Nome, Data_Arrivo, Data_Partenza e per esempio
con i seguenti valori:
Matteo    01-01-05    03-01-05
Pino        02-01-05    05-01-05
Luca        02-01-05   03-01-05
vorrei riuscire a fare una query che mi dicesse quante persone c'erano ogni
giorno e quante partite:
01-01-05       1    0
02-01-05       3    0
03-01-05       1    2
04-01-05       1    0
05-01-05       1    1
grazie a chi mi puņ essere di aiuto
matteo 

 ha scritto nel messaggio
news:cu838l$g4$1...@balena.cs.interbusiness.it...

Ciao Matteo,
si puņ fare ma non capisco bene il risultato...
Secondo il risultato dovrebbe essere questo
---------------
Data Presenze [Di Cui in partenza]
 01-01-05       1    0
 02-01-05       3    0
 03-01-05       3    2
 04-01-05       1    0
 05-01-05       1    1
----------------
Ciao Giorgio


in effetti giorgio hai ragione poiché le persone il 3-1-05 sono 3 di cui 2 
partite. chiedo scusa :-). Io non sono riuscito a fare una query che 
restituisca i dati in quella specie di tabella che tu hai riportato. Tu sei 
riuscito?
ciao e grazie 

 riuscito?
č abbastanza semplice, ti serve una tabella di supporto *Calendario* che
contiene un campo *Data*, la tabella deve contenere tutti i giorni
dell'anno, uno per riga.
La Query
--------------------
SELECT Data,
       (SELECT Count(1)
        FROM   T1
        WHERE  Data BETWEEN Data_Arrivo AND
               Data_Partenza) AS Presenze,
       (SELECT Count(1)
        FROM   T1
        WHERE  Data=Data_Partenza) AS In_Partenza
FROM    Calendario
WHERE   Data BETWEEN (SELECT MIN(Data_Arrivo) FROM T1) AND
                     (SELECT MAX(Data_Partenza) FROM T1)
---------------------
come vedi č composta di 4 subQuery, la prima restituisce le presenze per
ogni giorno, la seconda solo le partenze, la terza e la quarta che sono
nella clausola WHERE servono a filtrare solo i giorni interessati.
Il problema č che le subquery in presenza di molti dati rallentano molto
Access perchč vengono valutate riga per riga.
Sarebbe meglio trasformare le SubQuery in tabelle derivate sfruttando gli
inner e gli outer join del caso
es..
------------------------
SELECT Data,
       Count(1) AS Presenze,
       Val(Nz(In_Partenza ,0)) AS In_Uscita
FROM ((Calendario
  INNER JOIN
       (Select Min(Data_Arrivo) AS DA,
               Max(Data_Partenza) AS DP
        FROM   T1) AS Tx
        ON Calendario.Data>=Tx.DA AND
           Calendario.Data<=Tx.DP)
  LEFT JOIN
       (Select Data_Arrivo ,
               Data_Partenza
        FROM   T1) AS T2
        ON Calendario.Data>=T2.Data_Arrivo AND
           Calendario.Data<=T2.Data_Partenza)
  LEFT JOIN
        (Select Data_PArtenza,
                Count(1) AS In_Partenza
         FROM   T1
         GROUP BY Data_Partenza) T3
         ON Calendario.Data=T3.Data_Partenza
GROUP BY Data,In_Partenza
ORDER BY Data
--------------------------
Le due Query rendono esattamente lo stasso risultato, la seconda č piů
performante in Access.
Il discorso cambia con database piů professionali, infatti l'optimizer di
questi trasforma automaticamente la prima query nella seconda rendendo le
stesse prestazioni.
Ciao Giorgio

 05-01-05       1    1
Se la ricerca la devi fare su un intervallo di date (non per un giorno
specifico), una singola query mi pare possibile solo utilizzando una tabella
di "appoggio" contenente 365 records (uno per ogni giorno dell'anno).
Altrimenti dovrai scrivere del codice: un semplice loop da data a data e,
per ogni giorno, due o tre select sulla tabella T1.
HTH.
Alessandro

 05-01-05       1    1
come mi avevi giustamente fatto notare tu.
grazie ancora. matteo

 >
[CUT]

Ciao matteo,
visto che le presenze sono contate in modo corretto e le uscite no mi viene
da pensare che i campi Data_Arrivo e Data_Partenza non contengano la data
pura ma sono inquinati dalla parte ora. Oppure potrebbe non funzionare se la
tabella T_schedine contiene un campo di nome *Data*, in questo caso bisogna
usare l'alias per la tabella t_Calendario, comunque, visto che le presenze
sono contate in modo corretto sono propenso per la prima ipotesi.
Per il resto non vedo perchè non possa andare, prima di suggerire la
soluzione l'ho provata simulando i tuoi dati.
Ciao Giorgio

 news:36s980F...@individual.net...
alt !!! un errore c'è !!!!
--------------
SELECT t_Calendario.data, (SELECT Count(1)
        FROM   T_schedine
        WHERE  Data BETWEEN Data_Ingresso AND
               Data_Uscita) AS Presenze, (SELECT Count(1)
        FROM   T_Schedine
        WHERE  Data=Data_Uscita) AS In_Partenza
FROM t_Calendario
WHERE (((t_Calendario.data) Between (SELECT MIN(Data_ingresso) FROM
T_Schedine) And (SELECT MAX(Data_uscita) FROM T_Schedine)));
----------------
La seconda SubQuery deve prendere in considerazione la Data_Uscita non la
Data_Ingresso
:-)
Ciao Giorgio

 ha scritto nel 
messaggio news:42090b79$0$6302$5fc...@news.tiscali.it...



E' vero!!!! tutto risolto. Anzi con il tuo aiuto ho creato anche un altra
Sub conteggiando
anche gli arrivi giorno per giorno (ormai ho capito il meccanismo). Se non
ti sei ancora stufato di essermi di aiuto ti domando se e come é invece
possibile inserire anche un altro conteggio o meglio una suddivisione. In
pratica nella tabella T_Schedine io memorizzo anche la nazione da cui
arrivano le persone in un campo Nazione. Supposto che i soliti dati siano i
seguenti:
 1, matteo, 01-01-2005, 03-01-2005, italia; 2, pino, 02-02-2005, 05-01-2005,
francia; 3, luca,
02-01-2005, 03-01-2005, italia;
come faccio ad aggiungere una colonna nella query che mi dica la nazionalità
dei presenti sempre giorno per giorno? in pratica dei presenti il 02-01-2005
vorrei sapere che 2 sono italiani e uno francese. E' sempre una sub query da
fare(?) Ho provato a raggruppare per nazione ma sbaglio da qualche parte.
ciao giorgio e grazie ancora


umm l'appetito vien mangiando.....
Qui l'SQL di Access si ferma, devi appoggiarti a una funzione vba che per
ogni giorno ti renda il concatenamento delle nazioni e il numero dei
partecipanti
Questa è la funzione
-------------------
Function ElencoNazioni(ByVal Data As Variant)
Dim Result As Variant
Dim Rs As Object
Set Rs = CurrentDb.OpenRecordset( _
    "Select Count(1) AS Nr," & _
    "       Nazione " & _
    "From T_Schedine " & _
    "WHERE " & "#" & Format(Data, "yyyy/mm/dd") & "#" & _
    "       BETWEEN Data_Ingresso AND Data_Uscita " & _
    "GROUP BY Nazione")
Do Until Rs.EOF
   Result = Result & "; " & Rs!Nr & " - " & Rs!Nazione
   Rs.MoveNext
Loop
Rs.Close
Set Rs=Nothing
ElencoNazioni = LTrim(Mid(Result, 2))
End Function
------------------------
Che andrai a richiamare dalla query in questo modo
-------------------------
SELECT t_Calendario.data, (SELECT Count(1)
        FROM   T_schedine
        WHERE  Data BETWEEN Data_Ingresso AND
               Data_Uscita) AS Presenze, (SELECT Count(1)
        FROM   T_Schedine
        WHERE  Data=Data_Uscita) AS In_Partenza,
        ElencoNazioni(Data) AS Nazioni
FROM t_Calendario
WHERE (((t_Calendario.data) Between (SELECT MIN(Data_ingresso) FROM
T_Schedine) And (SELECT MAX(Data_uscita) FROM T_Schedine)));
---------------------------
Ciao Giorgio

 Questa è la funzione
[CUT]
perfetto. é esattamente quanto mi serviva. Ti chiedo (fino a quando avrai 
voglia di insegnarmi...) ancora questo (e giuro che poi mi faccio passare 
l'appetito): oltre a non saper realizzare quanto ti sto per chiedere, non so 
nemmeno a livello concettuale come é giusto impostare il problema. Se io 
creo nella T_Schedine un campo testo per ogni nazione Italia, Francia, ecc. 
e voglio memorizzare all'interno il valore numerico che ho ottenuto con la 
funzione devo usare una query di aggiornamento o va fatto da codice 
all'interno della funzione? in pratica ho cercato di analizzare riga per 
riga quanto mi hai postato e non so se ho interpretato bene la funzione:
Function ElencoNazioni(ByVal Data As Variant)
[CUT]
Do Until Rs.EOF
   Result = Result & "; " & Rs!Nr & " - " & Rs!Nazione
********* dovrei riuscire a questo punto memorizzare il valore Rs!Nr nel 
campo Italia, quindi Rs.Move.Next e di nuovo Rs!Nr nel campo Francia (ma 
come fare ?!?!)*********
   Rs.MoveNext
Loop
End Function
oppure é più corretto utilizzare la Select inserendo l'istruzione di 
aggiornare il valore dei campi Italia, Francia...
oppure non é corretta nessuna delle due impostazioni :-)
Spero di essermi spiegato.
Ciao Matteo

 ha scritto nel messaggio
news:371kceF...@individual.net...

umm la funzione e la query sono progettate e funzionano in base ai dati che
hai detto di avere
---------------
Nome Data_Ingresso Data_Uscita Nazione
Luca 02/01/2005 03/01/2005 Italia
Matteo 01/01/2005 03/01/2005 Italia
Pino 02/01/2005 05/01/2005 francia
---------------
e producono questo risultato
----------------
Data Presenze In_Partenza Nazioni
01/01/2005 1 0 1 - Italia
02/01/2005 3 0 1 - Francia; 2 - Italia
03/01/2005 3 2 1 - Francia; 2 - Italia
04/01/2005 1 0 1 - Francia
05/01/2005 1 1 1 - Francia
-------------------
non devi memorizzare nient'altro nella tabella T_Schedine il conteggio delle
nazioni e le loro descrizioni raggruppate e concatenate in un periodo di
tempo dipendono da più nominativi!!  non c'è nessuna relazione con un
singolo elemento, un singolo nominativo fa parte dell'insieme ma l'insieme
non è parte del singolo nominativo.
Scusa ma non riesco a capire la domanda
Ciao Giorgio


Forse ho capito dove sbagliavo (devo modificare la struttura di T_Calendario 
e non T_Schedine) e quindi perché non potevi capire.
Provo a spiegarmi rifacendo il ragionamento:
grazie al codice ho praticamente ottenuto il risultato che mi serviva, mi 
sono accorto facendo un pò di prove che se la nazioni sono tante mi verrà 
fuori una stringa con un valore lunghissimo, per esempio: "1 - Francia,  2 - 
Italia, 4 - Germania, 4 - Inghilterra, ecc". fino a tutte le possibili 
nazioni che ci possono essere. Diventa perciò difficile usare tale stringa 
anche in termini di getione del numero di caratteri (per esempio una stampa 
o una esportazione. Quello che mi sono detto allora é stato questo: io 
modifico la T_Calendario e codifico a priori gli stati creando un campo per 
ogni stato. quindi quando eseguo la query sarà sufficiente per ogni campo 
inserire (o meglio aggiornare) il valore numerico ottenuto con la query 
relativo al numero di presenze per ogni stato. In pratica dovrò aggiornare 
la T_Calendario in modo da ottenere il seguente risultato (valori ovviamente 
fittizi):
--------------------------
data        italia    francia    inghilterra   germania    olanda 
venuezuela
1-1        5            8                5            4                4 
2
2-1        0            2                3            2                1 
8
3-1        0            2                3            2                1 
8
4-1        1            3             .
5-1        0            2
---------------------------
spero di essere stato più chiaro e soprattutto di aver eseguito 
correttamente il ragionamento.
ciao Matteo

 ciao Matteo

 ha scritto nel messaggio
news:3737kkF...@individual.net...

puoi ottenere lo stesso risultato con una query a campi incrociati senza
modificare la tabella.
--------------
TRANSFORM Sum(NR) AS Partecipanti
SELECT Data
FROM (SELECT Data,Count(1) AS NR, Nazione
      FROM T_Schedine S
         INNER JOIN
           T_Calendario C ON C.Data>=S.Data_Ingresso AND
           C.Data<=S.Data_Uscita
      GROUP BY C.Data,S.Nazione) AS Tx
GROUP BY Data
PIVOT Nazione;
---------------
Ciao Giorgio


ho approffittato di questi due giorni per "studiare le query a campi 
incrociati" e a qualcosa sono arrivato. Solo che sia eseguendo il tuo codice 
che creandone uno nuovo, mi compare il messaggio "impossibile aprire il file 
msjter35.dll. ho cercato su internet e ho trovato il file da installare in 
sytem32, ma non funziona ugualmente. Sai che tipo di errore é e come 
correggere? Io lavoro con Access97. ciao e grazie Matteo
ps. peccato ero quasi arrivato al dunque.... -:) 


Ok funziona perfettamente :-). Strano perň che con l'autocomposizione mi 
creasse la query senza problemi ma che poi mi dava errore.
Un'ultima cosa. Non riesco a inserire anche i campi ottenuti con la prima 
query:
SELECT t_Calendario.data, (SELECT Count(1)
        FROM   T_schedine
        WHERE  Data BETWEEN Data_Ingresso AND
               Data_Uscita) AS Presenze, (SELECT Count(1)
        FROM   T_Schedine
        WHERE  Data=Data_Uscita) AS In_Partenza, (SELECT Count(1)
        FROM   T_Schedine
        WHERE  Data=Data_ingresso) AS In_arrivo
FROM t_Calendario
WHERE (((t_Calendario.data) Between (SELECT MIN(Data_ingresso) FROM
T_Schedine) And (SELECT MAX(Data_uscita) FROM T_Schedine)));
ho provato a salvare le due query e crearne una terza che unisca le due 
query ma esce un errore. Forse dovrei farne una sola, ma come devo 
intersecarle?
In pratica per ottenere una griglia cosě.
data        presenze   In_partenza    In_Arrivo    Italia    Francia 
Germania
1-1-05    4                   1                    1            1 
2               1
Ciao e grazie ancora
Matteo


per access 97 la sintassi cambia leggermente
------------------
 TRANSFORM Sum(NR) AS Partecipanti
 SELECT Data
 FROM [SELECT Data,Count(1) AS NR, Nazione
      FROM T_Schedine S
         INNER JOIN
           T_Calendario C ON C.Data>=S.Data_Ingresso AND
           C.Data<=S.Data_Uscita
      GROUP BY C.Data,S.Nazione]. Tx
 GROUP BY Data
 PIVOT Nazione;
---------------
se l'errore persiste prova ad aggiornare la tua versione di Jet 3.5
-----------------
http://support.microsoft.com/default.aspx?scid=kb;en-us;172733
-----------------
Ciao Giorgio


Ciao Matteo,
qui l'Sql di Access va in confusione :(
ti conviene usare le due query per creare due tabelle temporanee che poi
andrai a collegare in join in una nuova query per ottenere il risultato
voluto.
Ciao Giorgio


ho fatto come sempre un pò di tentativi... ma desolatamente senza risultati. 
mi spiego.
Ho creato le due tabelle temporanee, il problema che nella prima ho i 
seguenti risultati:
1a tabella (T_Presenze)
data           presenze    in partenza    in arrivo
02-01-05    4                    0                3
2a tabella (T_Nazioni)
data            nazione    partecipanti
02-01-05    italia                2
02-01-05    francia            1
02-01-05    germania        1
creando la query non riesco raggruppando per data ad ottenere un'unica riga 
riepilogativa
ma mi tiene sempre incolonnate le nazioni... ho fatto mille tentativi e sono 
sicuro che é una cosa
semplicissima... :-(
Ciao Matteo


Ciao Matteo,
allora ...
con la prima Query crei la tabella T_PresenzePartenze
---------------------
SELECT * INTO T_PresenzePartenze
FROM [SELECT t_Calendario.data, (SELECT Count(1)
        FROM   T_schedine
        WHERE  Data BETWEEN Data_Ingresso AND
               Data_Uscita) AS Presenze, (SELECT Count(1)
        FROM   T_Schedine
        WHERE  Data=Data_Uscita) AS In_Partenza
FROM t_Calendario
WHERE (((t_Calendario.data) Between (SELECT MIN(Data_ingresso) FROM
T_Schedine) And (SELECT MAX(Data_uscita) FROM T_Schedine)))]. AS Tx;
---------------------
La seconda Query
------------------------
TRANSFORM Sum(NR) AS Partecipanti
SELECT Data
FROM [SELECT Data,Count(1) AS NR, Nazione
      FROM T_Schedine S
         INNER JOIN
           T_Calendario C ON C.Data>=S.Data_Ingresso AND
           C.Data<=S.Data_Uscita
      GROUP BY C.Data,S.Nazione]. AS Tx
GROUP BY Data
PIVOT Nazione;
--------------------------
la salvi con nome Q_TotaliPerNazionee la usi in un'altra query per reare la
tabella T_TotaliPerNazione
-------------------------
SELECT Q_TotaliPerNazione.* INTO T_TotaliPerNazione
FROM Q_TotaliPerNazione;
-------------------------
a questo punto usi le tabelle create T_PresenzePartenze e T_TotaliPerNazione
in Join tramite il campo data per ottenere il risultato voluto.
Ciao Giorgio