Home Page
Articoli
Tips & Tricks
News
Forum
Archivio Forum
Blogs
Sondaggi
Rss
Video
Utenti
Chi Siamo
Contattaci
Username:
Password:
Login
Registrati ora!
Recupera Password
Home Page
Stanze Forum
SQL Server 2000/2005/2008, Express, Access, MySQL, Oracle
[SQLSrv] Da data a data - x
mercoledì 22 marzo 2006 - 10.07
Elenco Threads
Stanze Forum
Aggiungi ai Preferiti
Cerca nel forum
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
mer 22 mar 2006 - 10:07
In primo luogo vorrei ringraziare sentitamente chi mi ha risposto nel thread riguardante le variabili
Avrei un'altra domanda, molto più semplice della precedente (spero :P ):
Avendo una tabella con usrId e DataLogin (tipo 31/01/2005), dovrei fare alcune select tra la DataLogin e i 365 giorni precedenti a quella data. Cioè qualcosa tipo:
SELECT ...
FROM ...
WHERE DataLogin BETWEEN DataLogin-365 AND DataLogin
Dite che è possibile? Sapete per caso la sintassi corretta? Qualcosa tipo
WHERE (DataLogin BETWEEN CONVERT(datetime, DataLogin - 365, 120) AND CONVERT(datetime, DataLogin, 120))
Ma questo naturalmente dà errore :)
Di nuovo grazie a tutti quanti
alx_81
Profilo
| Guru
8.814
messaggi | Data Invio:
mer 22 mar 2006 - 10:33
In questo caso ti è utile la dateadd..
è una funzione che accetta come parametri la parte di data da aggiungere, il numero di unità, relativi alla parte, da aggiungere e la data da prendere in considerazione.
Avendo la tua tabella io farei:
select * from TuaTabella
where DataLogin between DATEADD(d,-365,DataLogin) and DataLogin
-- ovviamente aggiungi le condizioni necessarie per ottenere solo i record che ti interessano, se necessario.
In poche parole ho aggiunto -365 d (days) ad ogni DataLogin della tabella..
ok?
spero di esserti stato di aiuto!
fammi sapere!
ciao!
Alx81 =)
alx_81
Profilo
| Guru
8.814
messaggi | Data Invio:
mer 22 mar 2006 - 10:40
Se ti serve uno scalare con il numero di giorni intercorsi va bene la datediff.. altrimenti se ti serve una data o un elenco di date.. è meglio la dateadd..
Alx81 =)
lbenaglia
Profilo
| Guru
5.625
messaggi | Data Invio:
mer 22 mar 2006 - 10:46
>In primo luogo vorrei ringraziare sentitamente chi mi ha risposto
>nel thread riguardante le variabili
Ciao Hamelin [FL] ,
se ritieni di aver ricevuto informazioni utili, puoi votare la risposta migliore
>Avendo una tabella con usrId e DataLogin (tipo 31/01/2005), dovrei
>fare alcune select tra la DataLogin e i 365 giorni precedenti
>a quella data. Cioè qualcosa tipo:
>
>SELECT ...
>FROM ...
>WHERE DataLogin BETWEEN DataLogin-365 AND DataLogin
>
>Dite che è possibile? Sapete per caso la sintassi corretta?
SQL Server offre due data types per la memorizzazione delle date: datetime e smalldatetime.
datetime
--------
Range di validità: 1 gennaio 1753 - 31 dicembre 9999 con una precisione pari a 0.00333 secondi.
Bytes occupati: 8 (2 coppie di interi di 4 bytes)
- i primi 4 per la memorizzazione dei giorni prima o dopo l'1 gennaio 1900
- gli altri 4 per la memorizzazione dei millisecondi dopo la mezzanotte
smalldatetime
-------------
Range di validità: 1 gennaio 1900 - 6 giugno 2079 con una precisione al minuto.
Bytes occupati: 4 (2 coppie di interi di 2 bytes)
- i primi 2 per la memorizzazione dei giorni dopo l'1 gennaio 1900
- gli altri 2 per la memorizzazione dei minuti dopo la mezzanotte
In entrambi i casi la base date è 01/01/1900. Le date antecedenti la base
date saranno rappresentati da numeri negativi mentre quelle successive come
numeri positivi.
Come vedi le date sono memorizzate in coppie di numeri interi: il primo numero memorizza la data mentre il secondo l'ora.
> WHERE DataLogin BETWEEN DataLogin-365 AND DataLogin
Se il data type della colonna DataLogin è datetime o smalldatetime, l'operazione DataLogin-365 non fa altro che sottrarre 365 giorni dalle date memorizzate nella colonna DataLogin.
Ad ogni modo non capisco quella condizione di WHERE.... Che significa?
Verifichi che DataLogin sia compresa tra DataLogin di 1 anno fa e DataLogin stessa... in pratica questa condizione sarà sempre True quindi restituirai tutte le righe.
Secondo me dopo la BETWEEN dovrai specificare dei parametri di input o delle costanti nel formato 'YYYYMMDD'.
>Di nuovo grazie a tutti quanti
Prego.
Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
mer 22 mar 2006 - 12:13
Dunque: la funzione DateAdd fa proprio quello che chiedevo, quindi già di questo vi ringrazio
Ora provo a spiegare un po' meglio cosa mi serviva in modo che vediamo se sto dicendo cose sensate oppure no:
In pratica dovrei definire un utente in base al numero di login che ha fatto negli ultimi 12 mesi rispetto a ogni mese considerato. Se ha eseguito 1 login è un utente "Normal", se ne ha eseguite 2 è "Super". Questo controllo però non lo devo fare su una finestra "statica" di 12 mesi, ma sui 12 mesi precedenti a ogni mese di login. Quindi se la tabella delle login ha questi dati:
[UsrId] [DataLogin]
1 | 01/01/2005
1 | 02/01/2005
E, nel 2006, faccio la mia stima, l'utente 1 dev'essere definito 'Super' a gennaio 2006 (perchè negli ultimi 12 mesi, e cioè da gennaio 2005 a gennaio 2006, ha eseguito 2 login) e 'Normal' a febbraio 2006 (perchè negli ultimi 12 mesi, e cioè da febbraio 2005 a febbraio 2006, ha eseguito 1 login, visto che la prima non viene più considerata)
Probabilmente sbagliando, il modo che ho trovato di risolvere il problema è stato il seguente:
SELECT usrId,
CASE
WHEN COUNT(usrId) = 2 THEN 'Super'
ELSE 'Normal' END
AS TipoUtente
FROM TabellaLogin
WHERE DataLogin BETWEEN DATEADD(d, - 365, DataLogin) AND DataLogin
Io cioè speravo che, riga per riga, mi definisse l'utente in base alla data login di quella riga, e ai 12 mesi precedenti.
Sbaglio? Se sì, dite che esiste un modo per risolvere il mio problema?
Grazie per l'attenzione
alx_81
Profilo
| Guru
8.814
messaggi | Data Invio:
mer 22 mar 2006 - 12:18
Direi che va bene..hai fatto una cosa giusta..
magari metterei >1 invece di = 2... visto che un utente sarà super anche se si è loggato più di 2 volte no? =)))
io credo di averti dato l'aiuto corretto per quello che ti serviva..
DateAdd è ok..
a meno che chi ne sa più di me (e sono a miliardi) non trovi soluzioni più furbe..
allora copierò! =)
Ciao!
Alx81 =)
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
mer 22 mar 2006 - 13:01
Anch'io pensavo fosse giusta, ma non sembra funzionare come dovrebbe ^^" (sembra che la finestra non cambi riga per riga, ma sia fissa per tutta la stima)
Ora mi ci scorno un po' per tentare di capire meglio... magari sfugge uno di quegli errori logici minimi che rendono tutto completamente sbagliato :P
(comunque sì, in base alla mia richiesta iniziale la funzione che mi hai dato era proprio quella giusta, grazie mille :) )
lbenaglia
Profilo
| Guru
5.625
messaggi | Data Invio:
mer 22 mar 2006 - 13:30
>Anch'io pensavo fosse giusta, ma non sembra funzionare come dovrebbe
>^^" (sembra che la finestra non cambi riga per riga, ma sia fissa
>per tutta la stima)
Ciao Hamelin [FL],
come ti ho già spiegato nel precedente post quella condizione di ricerca è priva di senso e anche la logica che stai cercando di implementare mi è poco chiara.
Nel tuo precedente esempio dicevi:
> E, nel 2006, faccio la mia stima, l'utente 1 dev'essere definito 'Super' a gennaio 2006
> (perchè negli ultimi 12 mesi, e cioè da gennaio 2005 a gennaio 2006, ha eseguito 2 login)
> e 'Normal' a febbraio 2006 (perchè negli ultimi 12 mesi, e cioè da febbraio 2005 a febbraio 2006,
> ha eseguito 1 login, visto che la prima non viene più considerata)
Ma dove specifichi nella query che stai prendendo in considerazione gennaio 2006, febbraio 2006...?
>(comunque sì, in base alla mia richiesta iniziale la funzione
>che mi hai dato era proprio quella giusta, grazie mille :) )
Dato che devi semplicemente sottrarre da una data un certo numero di giorni, in questo caso la funzione DATEADD() può essere tranquillamente sostituita dall'operatore algebrico "-" generando meno overhead del dovuto.
Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
mer 22 mar 2006 - 14:11
> Ma dove specifichi nella query che stai prendendo in considerazione gennaio 2006, febbraio 2006...?
Provo a spiegare la logica che sto tenendo, sperando mi possiate dare una mano a rendere sensata la query, in base alle richieste:
- Parto dalla tabella con i campi UsrId e DataLogin
- Su questa faccio la view scritta sopra che mi definisce il tipo di utente in base a quante login ha fatto nei 12 mesi precedenti il valore del mese presente in DataLogin, aggiungendo un group by YEAR in modo che me li suddivida per anno (e già mi rendo conto che questo è un errore, è per questo motivo che la finestra mi resta statica: in realtà mi restituisce niente più che i tipi utenti raggruppati per anno, ma non tiene conto della mia clausola WHERE. Forse dovrei raggrupparli sulla finestra, anzichè mettere la finestra sul where, ma non saprei come)
Per fare questo speravo che mettendo "WHERE DataLogin BETWEEN DataLogin-365 AND DataLogin" mi considerasse appunto, riga per riga, i 12 mesi precedenti la data presente nel campo.
Da questa view ottengo una tabella del tipo [UsrId] [TipoUtente]
- Una seconda view mi serve appunto per tener conto del mese. Definisco questa view come
SELECT usrId, MONTH([Data Login]) AS Mese, YEAR([Data Login]) AS Anno
FROM Tabella
GROUP BY usrId, MONTH([Data Login]), YEAR([Data Login])
- A questo punto la query finale, tramite un join tra le due basato sull'usrId, gruppando per tipo utente, mese e anno mi restituisce la tabella [TipoUtente] [ConteggioLogin] [Mese] [Anno]
Dite che è risolvibile la richiesta del datore di lavoro? E' proprio sbagliato il mio ragionamento? Il problema credo sia sulla finestra scorrevole... Dovrei in qualche modo modificare la prima view in modo che non sia fissa su un intervallo temporale, ma che scorra sui 12 mesi precedenti il login
lbenaglia
Profilo
| Guru
5.625
messaggi | Data Invio:
mer 22 mar 2006 - 14:37
>Per fare questo speravo che mettendo "WHERE DataLogin BETWEEN
>DataLogin-365 AND DataLogin" mi considerasse appunto, riga per
>riga, i 12 mesi precedenti la data presente nel campo.
Ciao Hamelin [FL],
vedo che insisti su quella WHERE... ragioniamo insieme.
Supponiamo di avere DataLogin = '20060322'.
La WHERE sarebbe:
WHERE '20060322' BETWEEN '20050322' AND '20060322' che ovviamente è vera, ma lo sarebbe con qualsiasi data!!
Se vuoi ricevere un aiuto più mirato, posta un piccolo esempio con la struttura della tabella base (CREATE TABLE), alcune righe di prova (INSERT INTO) ed il result set che vorresti ottenere.
Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
mer 22 mar 2006 - 14:52
No no, come ti ho detto mi sono persuaso che quella clausola non ha senso e non è assolutamente risolutiva del mio problema :)
Purtroppo, però, non riesco a trovare una soluzione. Spero almeno di aver fatto capire cosa mi servirebbe:
Da una tabella degli usrId e DateLogin
UsrId | DataLogin
1 | 01/01/2005
1 | 01/02/2005
2 | 01/02/2005
3 | 02/02/2005
1 | 01/03/2005
Alla fine devo arrivare a una tabella che mi dica, per ogni mese, quanti sono gli utenti di ogni tipo
Mese | Tipo | NumeroUtentiPerTipo
1 | Sconosciuto | 2
1 | Normale | 1
2 | Sconosciuto | 1
2 | Normale | 1
Dove "Sconosciuto" e "Normale" del mese 1 lo definisco in base a quante login ha fatto nei 12 mesi precedenti al mese 1
Sconosciuto e Normale del mese 2 lo definisco in base a quante login ha fatto nei 12 mesi precedenti al mese 2
E così via
Ho dato sufficienti informazioni? Sono stato comprensibile? E soprattutto: sarà risolvibile in qualche modo?
Grazie davvero, sono un po' in panne...
lbenaglia
Profilo
| Guru
5.625
messaggi | Data Invio:
mer 22 mar 2006 - 15:46
>Ho dato sufficienti informazioni? Sono stato comprensibile? E
>soprattutto: sarà risolvibile in qualche modo?
A questo punto getto la sugna, mi dispiace ma non capisco la logica che vuoi applicare.
Vediamo se qualcun altro sarà in grado di darti una mano.
Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
mer 22 mar 2006 - 16:00
Nel caso non mi sia spiegato bene posso provare ad essere più chiaro
(si tratta di sapere, ogni mese, quante login ha fatto ogni "tipo di utente". E per stabilire il tipo di utente guardo quante login ha fatto un utente nell'arco di tempo pari a 12 mesi prima del mese che sto considerando)
Se invece è proprio la richiesta ad essere contorta/irrisolvibile nulla, massimo rassegnerò le mie dimissioni :P (perchè ovviamente se non si può fare non ci crederanno mai, e passerò io per incompetente - cosa peraltro vera in questo genere di cose)
Grazie comunque per l'aiuto, e speriamo che qualcuno sappia trovare una via percorribile
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
mer 22 mar 2006 - 16:39
La sintassi è scorrettissima, ma si dovrebbe risolvere con qualcosa tipo:
WHERE CASE
WHEN month([Data Login]) = 1 THEN [Data Login] BETWEEN '2004-01-01' AND '2005-01-01'
WHEN month([Data Login]) = 2 THEN [Data Login] BETWEEN '2004-02-01' AND '2005-02-01'
ELSE [Data Login] BETWEEN '2004-03-01' AND '2005-03-01'
END
Anche lasciando perdere il resto dell'architettura, c'è il modo di programmare in SQL qualcosa che faccia una cosa del genere?
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
gio 23 mar 2006 - 09:59
Mi è stata fornita questa soluzione:
WHERE (month (data_login) = 1 and data_login between 01/01/2005 and 01/01/2006)
or (month (data_login) = 2 and data_login between 01/02/2005 and 01/02/2006)
or (...)
Che è un po' macchinosa da fare per tutti i mesi dell'anno (servono 12 rami OR), però mi sembra corretta
Forse c'è un modo meno macchinoso, ma in pratica fa il check sul mese della data login: se è uguale a 1, allora clausola where usata è il between 01/2005 e 01/2006
Se il mese è uguale a 2 viene presa come data between 02/2005 e 02/2006
Eccetera
Sinceramente non riesco bene a capire se ci possa essere un errore #__# Ma mi sto aggrappando alla speranza che sia giusta :P
alx_81
Profilo
| Guru
8.814
messaggi | Data Invio:
gio 23 mar 2006 - 11:11
Anche se la migliori come leggibilità o implementazione, credo che serva per forza un dominio dei mesi dell'anno.. sennò sei costretto a riferirti alle sole mensilità che hai nella tabella delle login..
Se a te interessano tutti i mesi, ti serve il dominio, viceversa puoi utilizzare l'elenco delle date di login.
Ciao!
Alx81 =)
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
gio 23 mar 2006 - 11:32
Ho paura di non aver capito ^^"
alx_81
Profilo
| Guru
8.814
messaggi | Data Invio:
gio 23 mar 2006 - 11:38
Per avere l'elenco di tutti i mesi dell'anno, hai bisogno di creartelo..
semplice.. =)
Alx81 =)
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
gio 23 mar 2006 - 11:58
Ahhh capisco :)
Sì in effetti visto che la clausola WHERE non supporta cicli, mi dovrò creare la lista a mano di tutti i mesi (l'ho fatto, ma non sono sicuro sul funzionamento)
Comunque, sul mio problema generale, ne ho postato la spiegazione, ad esempio, qui (oltre che su tutti i forum attendibili di SQL che sto trovando):
http://www.oracleportal.it/oipforum/thread.jspa?forumID=17&threadID=5815&tstart=0
Speriamo che qualcuno sappia rispondere, inizio a disperarmi :)
Ovviamente se trovo la soluzione ve la posto per completezza :P
alx_81
Profilo
| Guru
8.814
messaggi | Data Invio:
gio 23 mar 2006 - 12:03
In poche parole..
Tu devi sapere ogni mese quante login ha fatto l'utente (andando a ritroso per un anno).
io ricaverei la distinct di ogni datalogin per utente in questo modo:
SELECT distinct UserId,DataLogin
FROM Tabella
-------------------------
1 2005-01-01
1 2005-02-01
1 2005-03-01
2 2005-02-01
3 2005-02-01
poi farei un cursore, macchinoso eh.. s'intenda!! =), però sembra andare bene..
DECLARE @UserId int
DECLARE @DataLogin datetime
DECLARE DATE_LOGIN CURSOR FOR
SELECT distinct UserId,DataLogin
FROM Logins
OPEN DATE_LOGIN
FETCH NEXT FROM DATE_LOGIN
INTO @UserId, @DataLogin
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @UserId,count(*),
CASE
WHEN count(*) <= 1 THEN 'Normale'
ELSE 'Super'
END
FROM Tabella
WHERE DataLogin >= DateAdd(dd,-365,DataLogin) AND DataLogin <= @DataLogin
AND UserId = @UserId
FETCH NEXT FROM DATE_LOGIN
INTO @UserId, @DataLogin
END
CLOSE DATE_LOGIN
DEALLOCATE DATE_LOGIN
cambia il nome della tabella.. i campi dovrebbero essere uguali ai tuoi..
fammi sapere!
Se qualcuno mi comunica un modo per fare questo cursore con una query me lo faccia sapere.. perchè così è un pochino macchinoso!
Alx81 =)
alx_81
Profilo
| Guru
8.814
messaggi | Data Invio:
gio 23 mar 2006 - 18:25
Hai provato???
sono curioso!! =)
Alx81 =)
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
ven 24 mar 2006 - 09:55
Poichè sto usando MS SQL Server Reporting Services, che io sappia non posso far interagire tra loro 2 query diverse. Cioè: non posso (che io sappia eh) creare una query che mi restituisca dei campi, e con un'altra query andare a interrogare quei campi.
Per fare questo al momento ho risolto creando delle view, che poi vado a interrogare con la query finale. Quindi quella che mi definisce il tipo di utente sarebbe una view.
E il guaio è che le view non possono avere dichiarazioni di variabili, quindi non posso seguire questa strada ^^"
alx_81
Profilo
| Guru
8.814
messaggi | Data Invio:
ven 24 mar 2006 - 10:18
fai una stored procedure..
Alx81 =)
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
ven 24 mar 2006 - 12:24
Temo di non essere in grado :P
Cmq vado sul concreto e posto l'implementazione, che con tutti questi discorsi di esempi e teorie non ci capisco più niente io, mi immagino voi :P
Questa è l'architettura _funzionante con finestra fissa_
La prima view che definisce il *Tipo di Utente* (chiamata TipoUtente2005):
SELECT usrId,
CASE WHEN COUNT(usrId) > 150 THEN 'Super'
ELSE 'Normal' END
AS TipoUtente, YEAR([Data Login]) AS Anno
FROM dbo.TabellaLogin
WHERE ([Data Login] BETWEEN '2004-12-01' AND '2005-12-01')
GROUP BY usrId, YEAR([Data Login])
HAVING (YEAR([Data Login]) = 2005)
La seconda view che serve a tener conto del mese in cui ha fatto login (chiamata PerMese2005):
SELECT usrId, MONTH([Data Login]) AS Mese, YEAR([Data Login]) AS Anno
FROM dbo.TabellaLogin
WHERE ([Data Login] BETWEEN '2005-01-01' AND '2005-12-31')
GROUP BY usrId, MONTH([Data Login]), YEAR([Data Login])
HAVING (YEAR([Data Login]) = 2005)
La query finale che, dal join tra le due view, ricava quanti utenti per tipo han loggato ogni mese:
SELECT dbo.TipoUtente2005.TipoUtente, COUNT(dbo.PerMese2005.Mese) AS Conteggio, dbo.PerMese2005.Mese, dbo.PerMese2005.Anno
FROM dbo.PerMese2005 INNER JOIN dbo.TipoUtente2005 ON dbo.PerMese2005.usrId = dbo.TipoUtente2005.usrId
GROUP BY dbo.TipoUtente2005.TipoUtente, dbo.PerMese2005.Mese, dbo.PerMese2005.Anno
ORDER BY dbo.PerMese2005.Mese
*****************************************************
Ora, il problema è trasformare la "finestra" temporale _fissa_ della prima view (WHERE [Data Login] BETWEEN '2004-12-01' AND '2005-12-01') in una finestra temporale _variabile_ (non definire il tipo utente sul 2005, ma sui 12 mesi precedenti a ogni mese considerato). Per fare questo mi è stato suggerito di trasformare quel where in qualcosa tipo:
WHERE (MONTH([Data Login]) = 1) AND ([Data Login] BETWEEN '2004-01-01' AND '2005-01-01') OR
(MONTH([Data Login]) = 2) AND ([Data Login] BETWEEN '2004-02-01' AND '2005-02-01') OR
(MONTH([Data Login]) = 3) AND ([Data Login] BETWEEN '2004-03-01' AND '2005-03-01') OR
(...)
Cioè è una sorta di ciclo case... Se il mese della data login è uguale a 1, allora attiva il primo ramo e considera la data login tra gen2004 e gen2005, se il mese è uguale a 2, attiva il secondo ramo e considera la data login tra feb2004 e feb2005
Benchè macchinosissimo, anche una soluzione così mi andrebbe bene. Il fatto è che questa non sembra funzionare (oltre a non essere affatto sicuro sul raggruppamento per anno che ho fatto. Poco male comunque: non funziona nè col raggruppamento per anno nelle 2 query, nè senza)
Come faccio a dire che non funziona? Con la finestra variabile, quando si arriva a dicembre la finestra variabile coincide con la finestra fissa usata nella query funzionante, quindi a dicembre i dati dovrebbero coincidere. Invece non è così.
alx_81
Profilo
| Guru
8.814
messaggi | Data Invio:
ven 24 mar 2006 - 12:40
sostituisci il nome della tabella (per me si chiama Logins), le etichette (Normale e super, per intenderci) ed esegui questo sql..
------
CREATE PROCEDURE [dbo].[spGetUserLoginLevel]
AS
DECLARE @UserId int
DECLARE @DataLogin datetime
CREATE TABLE #TempTable
(UserId int, Counter int, UserType varchar(50))
DECLARE DATE_LOGIN CURSOR FOR
SELECT distinct UserId,DataLogin
FROM Logins
OPEN DATE_LOGIN
FETCH NEXT FROM DATE_LOGIN
INTO @UserId, @DataLogin
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO #TempTable (UserId, Counter, UserType)
SELECT @UserId,count(*),
CASE
WHEN count(*) <= 1 THEN 'Normale'
ELSE 'Super'
END
FROM Logins
WHERE DataLogin >= DateAdd(dd,-365,DataLogin) AND DataLogin <= @DataLogin
AND UserId = @UserId
FETCH NEXT FROM DATE_LOGIN
INTO @UserId, @DataLogin
END
SELECT * FROM #TempTable
DROP TABLE #TempTable
CLOSE DATE_LOGIN
DEALLOCATE DATE_LOGIN
-------
Con questo sql crei la stored procedure..
Nel Reporting service, invece che eseguire una select fai: exec spGetUserLoginLevel, che ti tornerà la tabella che ti serve.. Se non riesci a saltarci fuori, chiedi pure..
ciao!
Alx81 =)
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
ven 24 mar 2006 - 17:15
Dunque dunque...
La stored procedure sono riuscito a crearla (già per lo sbattimento di averla fatta ti ringrazio infinitamente, purtroppo non sono capace di scriptarle), ora ho un problemuccio: poichè la tabella è di diverse migliaia di righe, purtroppo non sono ancora riuscito a vederne l'esecuzione finita ^^" Mi sa che è troppo pesante e si blocca
Quindi due piccole richieste (ho fatto un po' di prove ma si blocca sempre):
1) Come posso far sì di considerare, per prova, un piccolo periodo temporale anzichè tutta la tabella? Tipo mettergli da qualche parte un bel "WHERE DataLogin BETWEEN '2005-01-01' AND '2005-06-30'
2) Non sono sicuro di capire bene quando stiamo parlando della variabile DataLogin e del campo DataLogin della tabella originale (questo perchè in realtà il campo si chiama [Data Login], e non sono sicuro di averlo sostituito nei posti giusti)
3) (ancora da confermare): mi dà un errore di "Invalid object name #TempTable" (anche se tolgo il cancelletto)... ma forse questo è solo legato alla creazione di parametri che posso fare a mano... una volta che riuscirò a ottenere risultati senza far impalare il computer ti saprò dire :P
Chissà che non riusciamo finalmente a arrivare a una soluzione, nel frattempo comunque un grosso grazie
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
lun 27 mar 2006 - 10:37
Sono riuscito a risolvere tutti i problemi che avevo richiesto nel post precedente :)
Lo script funziona e sembra proprio giusto, quindi ti voto e ti ringrazio :P
Piccolo problema: il database è composto da centinaia di migliaia di righe, e per periodi temporali superiori a due settimane il server non ci sta più dietro. E l'azienda vorrebbe fare le stime su un intero anno.
Però direi che questo non è un problema dello script: è proprio la richiesta che implica la scansione del database milioni di volte (per ogni utente e per ogni mese prendere i 12 mesi precedenti, vedere quante volte ha loggato l'utente, contarlo, fare questa conta _per tutti_ gli utenti e contare ogni tipo utente). Speravo che il server aziendale ci stesse dietro, ma purtroppo non è così
Dubito ci sia una soluzione più veloce, quindi non mi resta che cercare di spiegare ai capi quanto sia complicato per il DB
Grazie davvero per l'impegno, spero vi abbia dato qualcosa come l'ha dato a me (nonostante la non riuscita, qualcosa ho sicuramente imparato, tra cui l'uso di Stored Procedure)
alx_81
Profilo
| Guru
8.814
messaggi | Data Invio:
lun 27 mar 2006 - 10:41
Riesci a scaricare la tabella su txt e zipparla?
così guardo se riesco ad ottimizzare.. grazie per il voto =)
ciaoooo!
Alx81 =)
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
lun 27 mar 2006 - 11:26
La tabella sono più di 350.000 righe di "userId" e "DataLogin" ^^"
Volendo ne puoi creare una a caso con date a caso, passarla mi sa ch esarebbe probitivo ^^"
Comunque la richiesta è pesantuccia, non so quanto sia ottimizzabile... inoltre non vorrei stressarti oltremisura e poi magari non si riesce a ottenere un risultato :)
alx_81
Profilo
| Guru
8.814
messaggi | Data Invio:
lun 27 mar 2006 - 13:26
E' pesante sì..
essendo inoltre un cursore..
puoi pensare di non fare la CASE, che è pesante.potresti pensare di farla applicativamente nel report.. già questo risparmia..
del resto non ho altre soluzioni =)
ok?
ciao!
Alx81 =)
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
mar 28 mar 2006 - 11:34
Ho pensato a una soluzione alternativa: eseguo la tua SP mese per mese (aggiungendo quindi un campo per il mese) e vado a salvare tutti i dati in una tabella che quindi sarà del tipo
[UserId] [Count] [TipoUtente] [Mese]
E poi tutte le interrogazioni le potrò fare su questa tabella definitiva :) In questo modo non mi interessa la pesantezza, visto che faccio tante piccole interrogazioni anzichè una sola grande
Che ne pensi?
Unico "problema", ho fatto un po' di prove ma non ne sono venuto a capo: come modifico la tua SP in modo che non accodi dati a una tabella temporanea, ma a una definitiva in modo da salvarceli? (la tabella l'ho già creata, la SP dovrebbe quindi andare a fare un INSERT dei nuovi dati)
Grazie ancora
alx_81
Profilo
| Guru
8.814
messaggi | Data Invio:
mar 28 mar 2006 - 13:37
devi fare la create table (con cotrollo di esistenza della tabella, e in quel caso drop) prima del cursore.. in questo modo:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[TUA_TABELLA]') AND type in (N'U'))
DROP TABLE [TUA_TABELLA]
CREATE TABLE [TUA_TABELLA]
(
[Userid] [int] NOT NULL,
[Data] datetime NOT NULL,
[Tipo] [varchar](50) NOT NULL
)
sostituisci TUA_TABELLA col nome della tua tabella fisica e commenta la parte di creazione della temporanea.
poi nel cursore devi fare la insert delle variabili che leggi col FETCH NEXT nella TUA_TABELLA, commentando la insert nella temporanea.
Alla fine hai una tabella fisica piena..
io riempivo una temporanea.. basta che la sostituisci..
tutto qui..
in alternativa puoi creare la tabella col designer di sql server e poi troncarla (truncate table TUA_TABELLA) ed inserire i valori da capo. In tal caso devi eliminare la creazione della temporanea e fare solo la insert sulla TUA_TABELLA.. chiaro??
ciao!
Alx81 =)
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
mar 28 mar 2006 - 13:45
Io ho creato la tabella TableType, e ho modificato la Stored Procedure nel seguente modo, sperando che questo mi inserisca i valori :P
LTER PROCEDURE dbo.spCreateTableType
AS
DECLARE @UserId int
DECLARE @DataLogin datetime
CREATE TABLE #TempTable
(UserId int, Counter int, UserType varchar(50), Mese int, Anno int)
DECLARE DATE_LOGIN CURSOR FOR
SELECT distinct usrId,[Data Login]
FROM TabellaLogin
WHERE [Data Login] BETWEEN '2005-01-01' AND '2005-01-31'
OPEN DATE_LOGIN
FETCH NEXT FROM DATE_LOGIN
INTO @UserId, @DataLogin
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO [TableType] (UserId, Counter, UserType, Mese, Anno)
SELECT @UserId,count(usrId),
CASE
WHEN count(usrId) > 75 THEN 'Super'
ELSE 'Normal'
END,
1, 2005
FROM dbo.EVO_UsersHistory
WHERE [Data Login] BETWEEN '2004-10-01' AND '2004-12-31'
AND usrId = @UserId
GROUP BY usrId
FETCH NEXT FROM DATE_LOGIN
INTO @UserId, @DataLogin
END
SELECT * FROM #TempTable
DROP TABLE #TempTable
CLOSE DATE_LOGIN
DEALLOCATE DATE_LOGIN
Ma mi sa che ho fatto una baggianata ^^" (io dovrei accodare i dati alla mia tabella, e non crearne una nuova ogni volta)
alx_81
Profilo
| Guru
8.814
messaggi | Data Invio:
mar 28 mar 2006 - 13:56
Personalmente utilizzerei la mia sp, per tutte le date, eseguendola prima di eseguire il report..
poi, quando hai la tabella fisica con meno righe, farei solo la query sulla tabella finale, a meno che non siano ancora troppe righe..
se la vuoi fare per mese, basta che lasci la mia logica, senza star lì a fare la tabella fisica, più lenta che la temporanea..
però metterei due parametri, l'anno ed il mese..
basta fare
alter procedure [proc_name]
(
@anno int,
@mese int
)
AS
...
e poi fai la where sullo year e sul month, invece che la between..
Alx81 =)
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
mar 28 mar 2006 - 14:04
Non posso eseguirla prima di eseguire il report perchè ci mette un sacco di tempo ^^"
Quindi devo per forza attuare la soluzione - brutta, me ne rendo conto - di crearmi a mano una tabella permanente con i dati estratti dalla tua SP
Però, avendo quella scritta qui sopra, non riesco ad adattarla per far sì che appunto faccia la INSERT in una tabella fissa, se eseguo quello che ho scritto mi dà "Invalid Object Name TableType", presumo sia perchè sbaglio la sintassi generale della SP di insert...
alx_81
Profilo
| Guru
8.814
messaggi | Data Invio:
mar 28 mar 2006 - 14:15
se noti, la mia sp inserisce già, ma in una tabella temporanea..
sostituisci la tabella temporanea con la tua.. anche nella create in alto.. e nella drop alla fine..
io intendevo di eseguirla di notte.. ed il giorno dopo fare la query sulla tabella fissa.. in modo da eseguire i processi divisi e distinti..
Alx81 =)
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
mar 28 mar 2006 - 14:28
Ma se faccio la drop alla fine non mi elimina la tabella che ho appena creato?
E avendo la tabella già creata quindi immagino basti eliminare la parte
CREATE TABLE #TempTable
(UserId int, Counter int, UserType varchar(50), Mese int, Anno int)
Però trasformando la SP come mi hai indicato, mi dà questo errore:
Running dbo."spCreateTableType".
Invalid object name 'TableType'.
No rows affected.
(0 row(s) returned)
@RETURN_VALUE =
Finished running dbo."spCreateTableType".
La SP l'ho appunto trasformata nella seguente:
ALTER PROCEDURE dbo.spCreateTableType
AS
DECLARE @UserId int
DECLARE @DataLogin datetime
DECLARE DATE_LOGIN CURSOR FOR
SELECT distinct usrId,[Data Login]
FROM TabellaLogin
WHERE [Data Login] BETWEEN '2005-01-01' AND '2005-01-31'
OPEN DATE_LOGIN
FETCH NEXT FROM DATE_LOGIN
INTO @UserId, @DataLogin
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO [TableType] (UserId, Counter, UserType, Mese, Anno)
SELECT @UserId,count(usrId),
CASE
WHEN count(usrId) > 75 THEN 'Super'
ELSE 'Normal'
END,
1, 2005
FROM TabellaLogin
WHERE [Data Login] BETWEEN '2004-10-01' AND '2004-12-31'
AND usrId = @UserId
GROUP BY usrId
FETCH NEXT FROM DATE_LOGIN
INTO @UserId, @DataLogin
END
SELECT * FROM [TableType]
CLOSE DATE_LOGIN
DEALLOCATE DATE_LOGIN
(scusami, mi sento davvero fesso ma non ci arrivo, mi devo trovare un manuale di come si scripano le SP...)
alx_81
Profilo
| Guru
8.814
messaggi | Data Invio:
mar 28 mar 2006 - 14:43
dovrebbe essere così..
ALTER PROCEDURE dbo.spCreateTableType
(
@from datetime,
@to datetime,
@from2 datetime,
@to2 datetime
)
AS
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[TableType]') AND type in (N'U'))
DROP TABLE [TableType]
CREATE [TableType]
(
UserId int,
Counter int,
UserType varchar(50),
Mese int,
Anno int
)
DECLARE @UserId int
DECLARE @DataLogin datetime
DECLARE DATE_LOGIN CURSOR FOR
SELECT distinct usrId,[Data Login]
FROM TabellaLogin
WHERE [Data Login] BETWEEN @from AND @to
OPEN DATE_LOGIN
FETCH NEXT FROM DATE_LOGIN
INTO @UserId, @DataLogin
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO [TableType] (UserId, Counter, UserType, Mese, Anno)
SELECT @UserId,count(usrId),
CASE
WHEN count(usrId) > 75 THEN 'Super'
ELSE 'Normal'
END,
Month(@from), Year(@from)
FROM TabellaLogin
WHERE [Data Login] BETWEEN @from2 AND @to2
AND usrId = @UserId
GROUP BY usrId
FETCH NEXT FROM DATE_LOGIN
INTO @UserId, @DataLogin
END
SELECT * FROM [TableType]
CLOSE DATE_LOGIN
DEALLOCATE DATE_LOGIN
Alx81 =)
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
mar 28 mar 2006 - 15:25
Mi sa che la mia niubbaggine e babbeaggine mi impediscano di farmi capire, e mi chiedo come fai ad avere ancora la pazienza di starmi dietro :P
Ma se faccio IF EXISTS ... DROP TABLE non mi elimina la tabella?
Cioè: io dovrei tenere la tabella fissa, e accodare ogni volta i campi
Cioè eseguo la SP per gennaio, e la tabella si riempie con i dati di gennaio
La rieseguo per febbraio, e i dati di febbraio si accodano a quelli già inseriti a gennaoi
La rieseguo per marzo, e i dati di marzo si accodano a gennaio e febbraio
Con quell'IF invece non si distrugge la tabella ad ogni esecuzione?
E se tolgo il blocco if (drop, create) mi dà il famoso errore "Invalid Object Name TableType" :(
alx_81
Profilo
| Guru
8.814
messaggi | Data Invio:
mar 28 mar 2006 - 15:37
allora creala e basta con uno script o dalla console..
e tira via il drop create sulla sp..
l'errore te lo da perchè la tabella non esiste..
e comunque, crea un id (come primary key identity) e un bell'indice sulla data.. così diventa più veloce (tiene di più sul disco ma le prestazioni aumentano notevolmente).
ok?
Alx81 =)
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
lun 3 apr 2006 - 11:53
Ri-edit
Sì confermo avevo detto una baggianata :P Ora mi dà risultati più congruenti
Premetto che va tutto bene e sembra proprio che sto riuscendo a fare quello che mi era stato chiesto.
Mi hanno dato una piccola modifica da fare: il count per la definizione utente non la dovrei fare sul numero di login, ma sul numero di login distinte per giorno (cioè se in un giorno faccio 1 o 100 login vale sempre per 1)
Ho modificato la SP in questo modo... avevo postato perchè dava risultati stranissimi, invece ho trovato l'errore e penso di averlo corretto in questo modo:
INSERT INTO [TableType] (UserId, Counter, UserType)
SELECT @UserId,count(distinct [Data Login]),
CASE
WHEN count(distinct [Data Login]) > 75 THEN 'Super'
WHEN count(distinct [Data Login]) > 50 AND count(distinct [Data Login]) <= 75 THEN 'Normal'
WHEN count(distinct [Data Login]) > 25 AND count(distinct [Data Login]) <= 50 THEN 'Occasionale'
WHEN count(distinct [Data Login]) > 1 AND count(distinct [Data Login]) <= 25 THEN 'Sleeper'
ELSE 'Sconosciuto'
END
FROM Tabella
WHERE [Data Login] BETWEEN '2005-09-01' AND '2005-11-30'
AND usrId = @UserId
GROUP BY usrId
Avevo il dubbio sul SELECT @UserId,count(distinct [Data Login]), ma sembra giusto quindi niente... se non è concettualmente sbagliato (non intendendomene di SP non so quando vanno usate le variabili e quando i campi della tabella) dovrei essere a posto :)
alx_81
Profilo
| Guru
8.814
messaggi | Data Invio:
lun 3 apr 2006 - 18:45
ci sta =)
cmq, io torno fra una settimana dall'irlanda.. quindi scusa se non rispondo per un po' =)
Alx81 =)
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
ven 14 apr 2006 - 11:15
EDIT DEFINITIVO: scusate, ritiro il post, in realtà è giusto così com'è, non è un errore
Oggi ho fatto la definizione degli utenti anche diviso per giorno, oltre che per mese. Quindi ho 2 SP:
*****
MESE:
*****
DECLARE DATE_LOGIN CURSOR FOR
SELECT usrId,[Data Login]
FROM dbo.EVO_UsersHistory
WHERE [Data Login] BETWEEN @DataInizio AND @DataFine
OPEN DATE_LOGIN
FETCH NEXT FROM DATE_LOGIN
INTO @UserId, @DataLogin
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO [TableType] (UserId, Counter, UserType, Mese, Anno)
SELECT @UserId,count(distinct [Data Login]),
CASE
WHEN count(distinct [Data Login]) > 48 THEN '5.Super'
WHEN count(distinct [Data Login]) > 12 AND count(distinct [Data Login]) <= 48 THEN '4.Normal'
ELSE '3.Occasionale'
END,
@Mese, @Anno
FROM dbo.EVO_UsersHistory
WHERE [Data Login] BETWEEN @DataInizioStima AND @DataFineStima
AND usrId = @UserId
GROUP BY usrId
FETCH NEXT FROM DATE_LOGIN
INTO @UserId, @DataLogin
END
*******
GIORNO:
*******
DECLARE DATE_LOGIN CURSOR FOR
SELECT usrId,[Data Login]
FROM dbo.EVO_UsersHistory
WHERE [Data Login] BETWEEN @DataInizio AND @DataFine
OPEN DATE_LOGIN
[...]
INSERT INTO [TableTypeDay] (UserId, Counter, UserType, Giorno, Mese, Anno)
SELECT @UserId,count(distinct [Data Login]),
CASE
WHEN count(distinct [Data Login]) > 48 THEN '5.Super'
WHEN count(distinct [Data Login]) > 12 AND count(distinct [Data Login]) <= 48 THEN '4.Normal'
ELSE '3.Occasionale'
END,
@Giorno, @Mese, @Anno
FROM dbo.EVO_UsersHistory
WHERE [Data Login] BETWEEN @DataInizioStima AND @DataFineStima
AND usrId = @UserId
GROUP BY usrId
****
Ma c'è qualcosa che non va. Il numero di accessi mensili dovrebbe essere uguale alla somma del numero di accessi giornalieri di quel mese, no?
Invece il numero di accessi giornalieri è molto, molto maggiore (in un mese 500 accessi, e ogni giorno di quel mese circa 100 accessi)
Guardandoli separatamente i dati sembrano comunque giusti (pochi accessi a agosto, pochi accessi nei weekend eccetera), eppure c'è questa cosa della conta che non torna.
C'è forse qualcosa di sbagliato che non riesco a vedere?
Per quanto riguarda le variabili, puntualizzo che:
Ricordo che l'utente va definito nel seguente modo: Nel mese 1, l'utente è Super se nei 3 mesi precedenti a 1 (quindi 10, 11 e 12), ha fatto tot login.
Quindi:
@DataInizio e @DataFine (quellendel cursor) sono rispettivamente 01/01/06 e 31/01/06
@DataInizioStrima e @DataFineStima (quelle della select) sono rispettivamente 01/10/05 e 31/12/05
Nel giornaliero invere, nel giorno 1 mese 1, l'utente è super se nei 3 mesi precedenti il giorno 1 e mese 1 ha fatto tot login
Quindi:
@DataInizio e @DataFine sono il giorno 1, quindi 01/01/06 e 01/01/06
@DataInizioStima e @DataFineStima sono ancora 01/10/05 e 31/12/05 (con la differenza che nella stima precedente si spostano di mese in mese, qui di giorni in giorno)
Ho forse sbagliato qui e doveva esssere il contrario? Notate altri possibili errori?
***********
EDIT dopo un controllo:
Dunque, qualcosa che torna c'è, ed è quello che io pensavo fosse il numero di accessi mensili (mentre non torna il numero di utenti)
Forse semplicemente non ho ben capito cosa ritorna questa SP: mi ritorna una tabella del tipo
UserId ConteggioTreMesiPrecedenti TipoUtente Mese Anno
E ogni utente compare tante volte quante sono le volte che ha fatto login in quel mese
Io facevo una SELECT COUNT(DISTINCT UserId) per fare la tabella degli utenti mensili... ma a quel punto se un utente ha loggato in un mese 10 volte me lo contava una volta sola, giusto?
Invece dovrei fare anche nella query una count distinct sulla data... insomma, inizio a capire qualcosa, scusate, vedo di chiarirmi le idee
alx_81
Profilo
| Guru
8.814
messaggi | Data Invio:
mar 18 apr 2006 - 12:56
vorrei aiutarti =), visto che ti ho procurato parte del problema, ma temo di essermi perso =)
Alx81 =)
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
ven 28 apr 2006 - 15:55
Ho notato solo ora, andando a ripescare questo thread, che mi avevi risposto... avevo fatto casini con gli EDIT, ma in realtà alla fine volevo dire che funzionava tutto ed ero a posto :)
Scusami se abuso di nuovo della tua disponibilità, ma mi è uscito un altro problema (ormai siamo agli sgoccioli però, fatte queste cose ho finito :P )
In pratica alla stored procedure perfettamente funzionante cui eravamo giunti:
****************************
ALTER PROCEDURE dbo.spCreateTableType
AS
DECLARE @UserId int
DECLARE @DataLogin datetime
DECLARE @DataInizio datetime
DECLARE @DataFine datetime
DECLARE @NuovoIscritto datetime
DECLARE @Mese int
DECLARE @Anno int
DECLARE @DataInizioStima datetime
DECLARE @DataFineStima datetime
SET @DataInizio = '2006-04-01'
SET @DataFine = '2006-04-30'
SET @NuovoIscritto = '01/03/2006'
SET @Mese = 4
SET @Anno = 2006
SET @DataInizioStima = '2006-01-01'
SET @DataFineStima = '2006-03-31'
DELETE FROM dbo.TableType
WHERE (Mese = @Mese) AND (Anno = @Anno)
DECLARE DATE_LOGIN CURSOR FOR
SELECT usrId,[Data Login]
FROM dbo.EVO_UsersHistory
WHERE [Data Login] BETWEEN @DataInizio AND @DataFine
OPEN DATE_LOGIN
FETCH NEXT FROM DATE_LOGIN
INTO @UserId, @DataLogin
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO [TableType] (UserId, Counter, UserType, Mese, Anno, AreaCommerciale, AnnoNascita, GruppoTBP, GruppoD2B, GruppoSeniorAccount, GruppoTeleAccount)
SELECT @UserId,count(distinct dbo.EVO_UsersHistory.[Data Login]),
CASE
WHEN count(distinct dbo.EVO_UsersHistory.[Data Login]) > 0 AND dbo.EVO_Users.[Data iscrizione] > @NuovoIscritto THEN '1.Nuovo iscritto'
WHEN count(distinct dbo.EVO_UsersHistory.[Data Login]) > 48 THEN '5.Super'
WHEN count(distinct dbo.EVO_UsersHistory.[Data Login]) > 12 AND count(distinct dbo.EVO_UsersHistory.[Data Login]) <= 48 THEN '4.Normal'
WHEN count(distinct dbo.EVO_UsersHistory.[Data Login]) > 1 AND count(distinct dbo.EVO_UsersHistory.[Data Login]) <= 12 THEN '3.Occasionale'
WHEN count(distinct dbo.EVO_UsersHistory.[Data Login]) = 1 THEN '2.Sleeper'
END,
@Mese, @Anno, dbo.EVO_Users.[Area Commerciale], YEAR(dbo.EVO_Users.[Data di Nascita]), dbo.EVO_Users.[Gruppo TBP], dbo.EVO_Users.[Gruppo D2B], dbo.EVO_Users.[Gruppo Senior Account], dbo.EVO_Users.[Gruppo Tele Account]
FROM dbo.EVO_UsersHistory INNER JOIN dbo.EVO_Users ON dbo.EVO_UsersHistory.usrId = dbo.EVO_Users.usrId
WHERE [Data Login] BETWEEN @DataInizioStima AND @DataFineStima
AND dbo.EVO_UsersHistory.usrId = @UserId AND (dbo.EVO_Users.[Abilitato al punteggio] = 'Abilitato') AND (dbo.EVO_Users.[Abilitato a ESms] = 'Abilitato') AND (dbo.EVO_Users.[Data cessazione] IS NULL OR dbo.EVO_Users.[Data cessazione] > @DataFine)
GROUP BY dbo.EVO_UsersHistory.usrId, dbo.EVO_Users.[Data iscrizione], dbo.EVO_Users.[Area Commerciale], dbo.EVO_Users.[Data di Nascita], dbo.EVO_Users.[Gruppo TBP], dbo.EVO_Users.[Gruppo D2B], dbo.EVO_Users.[Gruppo Senior Account], dbo.EVO_Users.[Gruppo Tele Account]
FETCH NEXT FROM DATE_LOGIN
INTO @UserId, @DataLogin
END
SELECT * FROM [TableType]
CLOSE DATE_LOGIN
DEALLOCATE DATE_LOGIN
**************************
Dovrei modificare la parte della CASE WHEN in modo da inserire una cosa del genere:
**************************
Select Q.UserID, Q.Conteggio,
(CASE WHEN Conteggio > 48 THEN '5.Super'
ELSE
CASE WHEN (Conteggio > 12 AND Conteggio <= 48)
AND (CDL15 > 2) AND (CDL3015 > 2) AND (CDL4530 >2)
THEN '4.Normal'
ELSE '3.Occasionale'
END
END) AS Tipo
FROM
(
SELECT UserId,count(distinct DataLogin) AS Conteggio,
(
select count(distinct DataLogin) FROM TabellaLogin
where UserID=T.UserID
and DataLogin BETWEEN DATEADD(day, -15, @DataInizio) AND @DataInizio
) as CDL15,
(
select count(distinct DataLogin) FROM TabellaLogin
where UserID=T.UserID
and DataLogin BETWEEN DATEADD(day, -30, @DataInizio) AND DATEADD(day, -15, @DataInizio)
) as CDL3015,
(
select count(distinct DataLogin) FROM TabellaLogin
where UserID=T.UserID
and DataLogin BETWEEN DATEADD(day, -45, @DataInizio) AND DATEADD(day, -30, @DataInizio)
) as CDL4530
FROM TabellaLogin T
WHERE T.DataLogin BETWEEN '01/01/2006' AND '01/04/2006'
group by UserID
) as q
**********************************
Io avevo provato a modificarla in questo modo, ma non funziona :(
**********************************
ALTER PROCEDURE dbo.spCreateTableType
AS
DECLARE @UserId int
DECLARE @DataLogin datetime
DECLARE @DataInizio datetime
DECLARE @DataFine datetime
DECLARE @NuovoIscritto datetime
DECLARE @Mese int
DECLARE @Anno int
DECLARE @DataInizioStima datetime
DECLARE @DataFineStima datetime
SET @DataInizio = '2006-04-01'
SET @DataFine = '2006-04-30'
SET @NuovoIscritto = '01/03/2006'
SET @Mese = 4
SET @Anno = 2006
SET @DataInizioStima = '2006-01-01'
SET @DataFineStima = '2006-03-31'
DELETE FROM dbo.TableType
WHERE (Mese = @Mese) AND (Anno = @Anno)
DECLARE DATE_LOGIN CURSOR FOR
SELECT usrId,[Data Login]
FROM dbo.EVO_UsersHistory
WHERE [Data Login] BETWEEN @DataInizio AND @DataFine
OPEN DATE_LOGIN
FETCH NEXT FROM DATE_LOGIN
INTO @UserId, @DataLogin
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO [TableType] (UserId, Counter, UserType, Mese, Anno, AreaCommerciale, AnnoNascita, GruppoTBP, GruppoD2B, GruppoSeniorAccount, GruppoTeleAccount)
SELECT Q.UserId,Q.Conteggio,
CASE
WHEN Q.Conteggio > 0 AND Q.DataIscrizione > @NuovoIscritto THEN '1.Nuovo iscritto'
WHEN Q.Conteggio > 48 THEN '5.Super'
WHEN (Q.Conteggio > 12 AND Q.Conteggio <= 48) AND (CDL15 > 2) AND (CDL3015 > 2) AND (CDL4530 > 2) THEN '4.Normal'
WHEN Q.Conteggio > 1 AND Q.Conteggio <= 12 THEN '3.Occasionale'
WHEN Q.Conteggio = 1 THEN '2.Sleeper'
ELSE '3.Occasionale'
END,
@Mese, @Anno, Q.AC, Q.AnnoNascita, Q.TBP, Q.D2B, Q.Senior, Q.Tele
FROM
(
SELECT @UserId AS UserId,count(distinct dbo.EVO_UsersHistory.[Data Login]) AS Conteggio, dbo.EVO_Users.[Data iscrizione] AS DataIscrizione, dbo.EVO_Users.[Area Commerciale] AS AC, YEAR(dbo.EVO_Users.[Data di Nascita]) AS AnnoNascita, dbo.EVO_Users.[Gruppo TBP] AS TBP, dbo.EVO_Users.[Gruppo D2B] AS D2B, dbo.EVO_Users.[Gruppo Senior Account] AS Senior, dbo.EVO_Users.[Gruppo Tele Account] AS Tele,
(
select count(distinct dbo.EVO_UsersHistory.[Data Login]) FROM dbo.EVO_UsersHistory
where UserID=dbo.EVO_UsersHistory.UserID
and dbo.EVO_UsersHistory.[Data Login] BETWEEN DATEADD(day, -15, @DataInizio) AND @DataInizio
) as CDL15,
(
select count(distinct dbo.EVO_UsersHistory.[Data Login]) FROM dbo.EVO_UsersHistory
where UserID=dbo.EVO_UsersHistory.UserID
and dbo.EVO_UsersHistory.[Data Login] BETWEEN DATEADD(day, -30, @DataInizio) AND DATEADD(day, -15, @DataInizio)
) as CDL3015,
(
select count(distinct dbo.EVO_UsersHistory.[Data Login]) FROM dbo.EVO_UsersHistory.[Data Login]
where UserID=dbo.EVO_UsersHistory.UserID
and dbo.EVO_UsersHistory.[Data Login] BETWEEN DATEADD(day, -45, @DataInizio) AND DATEADD(day, -30, @DataInizio)
) as CDL4530
FROM dbo.EVO_UsersHistory INNER JOIN dbo.EVO_Users ON dbo.EVO_UsersHistory.usrId = dbo.EVO_Users.usrId
WHERE [Data Login] BETWEEN @DataInizioStima AND @DataFineStima
AND dbo.EVO_UsersHistory.usrId = @UserId AND (dbo.EVO_Users.[Abilitato al punteggio] = 'Abilitato') AND (dbo.EVO_Users.[Abilitato a ESms] = 'Abilitato') AND (dbo.EVO_Users.[Data cessazione] IS NULL OR dbo.EVO_Users.[Data cessazione] > @DataFine)
GROUP BY dbo.EVO_UsersHistory.usrId, dbo.EVO_Users.[Data iscrizione], dbo.EVO_Users.[Area Commerciale], dbo.EVO_Users.[Data di Nascita], dbo.EVO_Users.[Gruppo TBP], dbo.EVO_Users.[Gruppo D2B], dbo.EVO_Users.[Gruppo Senior Account], dbo.EVO_Users.[Gruppo Tele Account]
) AS Q
FETCH NEXT FROM DATE_LOGIN
INTO @UserId, @DataLogin
END
SELECT * FROM [TableType]
CLOSE DATE_LOGIN
DEALLOCATE DATE_LOGIN
*******************************
Mi rendo conto dell'estremo caos che ho generato, e capisco che potresti non capirci niente di tutto quello che ho postato ^^"
Se invece ci capissi qualcosa, avresti idea di come modificare il tutto per far funzionare quella logica? (in pratica dovrei definire l'utente "Normal" non solo in base al numero di login fatte, ma dovrebbe aver anche fatto 2 login negli ultimi 15 giorni, 2 login da 30 a 15 giorni fa, e 2 login da 45 a 30 giorni fa)
Grazie di nuovo per tutti gli aiuti che mi hai dato... quand'è che ti posso offrire qualcosa?
alx_81
Profilo
| Guru
8.814
messaggi | Data Invio:
ven 28 apr 2006 - 17:43
Non mi devi offrire nulla =) no problema..
il problema vero è che non seguendo più il tuo caso ho completamente scordato tutto.. e non riesco a saltarci fuori.. è diventata enorme..
l'unica cosa che mi viene da pensare è di utilizzare delle count in subquery, filtrate per utente..
di più non ti so dire..
scusami..
Alx81 =)
http://blogs.dotnethell.it/suxstellino
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
mar 2 mag 2006 - 10:06
Sì è decisamente lunghissima, fatico a raccapezzarmici pure io
Comunque questo era solo un "di più", la Stored Procedure va benissimo anche così com'è, e ti ringrazio di nuovo perchè senza di te non ce l'avrei fatta :P
Mi hai fatto guadagnare un posto di lavoro :D
Grazie ancora, e saluti a tutti
alx_81
Profilo
| Guru
8.814
messaggi | Data Invio:
mar 2 mag 2006 - 10:11
un posto di lavoro??? =)
Alx81 =)
http://blogs.dotnethell.it/suxstellino
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
mar 2 mag 2006 - 10:23
Sì sono tirocinante e se riuscivo a fare bene questa cosa mi assumevano :P
alx_81
Profilo
| Guru
8.814
messaggi | Data Invio:
mar 2 mag 2006 - 10:28
beh.. grande allora! =)
Alx81 =)
http://blogs.dotnethell.it/suxstellino
Torna su
Stanze Forum
Elenco Threads
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?
Dopo esserti registrato potrai chiedere
aiuto sul nostro
Forum
oppure aiutare gli altri
Consulta le
Stanze
disponibili.
Registrati ora !