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
[SQL] Comparire in una tabella una volta al mese
mercoledì 19 aprile 2006 - 14.25
Elenco Threads
Stanze Forum
Aggiungi ai Preferiti
Cerca nel forum
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
mer 19 apr 2006 - 14:25
Un saluto a tutti
Ho una piccola richiesta su una possibile soluzione di un'interrogazione SQL
In pratica attualmente ho una SELECT CASE che definisce un utente in base al numero di volte che compare nella colonna "Data Login", tipo
SELECT
CASE
WHEN count([Data Login]) > 10 THEN 'Super'
WHEN count([Data Login]) > 1 AND count([Data Login]) < 10 THEN 'Normal'
ELSE 'Sleeper'
END
AS TipoUtente
Dovrei modificare la seconda condizione in modo che utente sia sì "Normal" se ha fatto da 1 a 10 login, ma anche che abbia anche fatto almeno 1 login al mese negli ultimi 3 mesi. Cioè un utente che ha fatto 5 login 3 mesi fa sia "Sleeper", mentre un utente che ha fatto 1 login nell'ultimo mese, 1 nel mese prima, e 1 nel mese ancora precedente sia "Normal"
Purtroppo non sono ancora riuscito a trovare una soluzione per questo piccolo rompicapo... qualcuno mi sa aiutare?
Spero di essere stato chiaro, in caso contrario fatemi un fischio e vedo di spiegarmi meglio. Grazie mille
lbenaglia
Profilo
| Guru
5.625
messaggi | Data Invio:
mer 19 apr 2006 - 14:31
>Purtroppo non sono ancora riuscito a trovare una soluzione per
>questo piccolo rompicapo... qualcuno mi sa aiutare?
Ciao Hamelin [FL],
aiutaci tu postando la struttura della tabella (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 19 apr 2006 - 14:59
La tabella ha le colonne "UserId" (intero) e "Data Login" (data), ad esempio
[UserId] [Data Login]
1 01/01/2006
2 01/01/2006
2 02/01/2006
1 01/02/2006
2 01/02/2006
1 01/03/2006
La query quindi dovrebbe restituire:
[UserId] [TipoUtente]
1 Super
2 Normal
Però mi servirebbe che questa cosa sia inserita nella SELECT CASE postata sopra, perchè in realtà questa è una semplificazione di una struttura più complessa che devo implementare in quel modo.
Insomma, io riesco già a fare la tabella "UserId - TipoUtente", ma al momento mi creerebbe 2 utenti super perchè entrambi hanno fatto 3 login. Invece mi servirebbe che il 2 venga definito Normal perchè non ha fatto una login al mese, ma 2 in un mese e 1 in un altro
Spero di avervi fornito gli strumenti necessari
lbenaglia
Profilo
| Guru
5.625
messaggi | Data Invio:
mer 19 apr 2006 - 15:08
>Spero di avervi fornito gli strumenti necessari
Direi che non ci siamo. Io ho chiesto la struttura della tabella (quindi il comando CREATE TABLE) e alcune righe di prova (comando INSERT INTO). Inoltre se applichi la tua SELECT ai dati che hai postato non otterrai il risultato voluto.
E' così difficile fare un esempio completo e funzionante?
--
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 19 apr 2006 - 15:25
Il fatto è che non uso il create table e l'insert into perchè uso SQL Server reporting services che si comporta tipo access, comunque provo a farli io a mano sperando che siano giusti :)
CREATE TABLE TableType
( UserId int
DataLogin date )
INSERT INTO TableType (UserId, DataLogin) VALUES (1, '01/01/2006') ... (ecc come quelli postati sopra)
E quindi la query dovrebbe essere qualcosa tipo:
SELECT UserId,
CASE
WHEN count([DataLogin]) > 2 THEN 'Super'
WHEN count([DataLogin]) > 1 AND count([DataLogin]) <= 2 AND *** THEN 'Normal'
ELSE 'Sleeper'
END
AS TipoUtente
FROM TableType
E dovrei fare la modifica nella parte "AND ***" in modo che non sia sufficiente il numero di volte in cui un utente compare nella tabella a definirlo, ma serva anche che abbia fatto almeno 1 accesso al mese (e non da 1 a 2 accessi indifferentemente)
Se non mi sbaglio ora come ora e senza la parte "AND ***" la query dovrebbe fornire
1 Super
2 Super
Invece mi servirebbe che dia
1 Super
2 Normal
Spero questa volta di aver dato le informazioni corrette
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
mer 26 apr 2006 - 09:23
Scusate se riuppo, sarà l'ultima volta poi mi rassegnerò :)
Ho dato di nuovo informazioni poco chiare/sono stato scortese, oppure il problema sembra non avere soluzione?
Grazie comunque per l'attenzione
escaflowne
Profilo
| Junior Member
180
messaggi | Data Invio:
mer 26 apr 2006 - 17:50
>Scusate se riuppo, sarà l'ultima volta poi mi rassegnerò :)
>
>Ho dato di nuovo informazioni poco chiare/sono stato scortese,
>oppure il problema sembra non avere soluzione?
>
>Grazie comunque per l'attenzione
ciao,
io credo che lbenaglia voglia proprio gli script (di creazione della tabella, di insert dei dati ecc). Così può replicare la situazione sul suo db e darti una soluzione puntuale.
Comunque, mi par di capire, che sia solo un problema di logica della clausola where.
cioè qualcosa tipo
Normal se 0<login<11
and (login > 1 and dataLogin = meseCorrente - 1)
and (login > 1 and dataLogin = meseCorrente - 2)
and (login > 1 and dataLogin = meseCorrente - 3)
da tradurre in sql (scusami ma ora non ho tempo di provare)
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
gio 27 apr 2006 - 15:04
In tal caso credo sia colpa della mia ignoranza, non saprei cos'altro fornire oltre a quello che ho dato ^^" (ma se posso, ovviamente, scrivo volentieri)
Comunque sì, forse si può risolvere anche solo con un po' di logica nel WHERE (o meglio, nelle clausole WHEN del CASE perchè il WHERE non lo posso toccare), e in effetti una soluzione come quella che proponi, se sviluppata, potrebbe portare a quanto richiesto... beh, provo a smanettarci un po' :)
***
Eccoci dopo la prova di smanettamento: dicevi qualcosa del genere?
WHEN count(distinct [Data Login]) > 1 AND count(distinct [Data Login]) <= 10
AND (([Data Login] > DATEADD(day, -30, @DataInizio)) AND (count(distinct [Data Login]) > 1))
AND (([Data Login] BETWEEN DATEADD(day, -60, @DataInizio) AND DATEADD(day, -30, @DataInizio)) AND (count(distinct [Data Login]) > 1))
THEN 'Normal'
O è completamente errato dal punto di vista logico? ^^"
escaflowne
Profilo
| Junior Member
180
messaggi | Data Invio:
gio 27 apr 2006 - 16:22
>In tal caso credo sia colpa della mia ignoranza, non saprei cos'altro
>fornire oltre a quello che ho dato ^^" (ma se posso, ovviamente,
>scrivo volentieri)
>
>Comunque sì, forse si può risolvere anche solo con un po' di
>logica nel WHERE (o meglio, nelle clausole WHEN del CASE perchè
>il WHERE non lo posso toccare), e in effetti una soluzione come
>quella che proponi, se sviluppata, potrebbe portare a quanto
>richiesto... beh, provo a smanettarci un po' :)
>
>***
>
>Eccoci dopo la prova di smanettamento: dicevi qualcosa del genere?
>
>WHEN count(distinct [Data Login]) > 1 AND count(distinct [Data
>Login]) <= 10
>AND (([Data Login] > DATEADD(day, -30, @DataInizio)) AND (count(distinct
>[Data Login]) > 1))
>AND (([Data Login] BETWEEN DATEADD(day, -60, @DataInizio) AND
>DATEADD(day, -30, @DataInizio)) AND (count(distinct [Data Login])
>> 1))
>THEN 'Normal'
>
>O è completamente errato dal punto di vista logico? ^^"
Si, credo che si possa fare questo tentativo. Pensavo che, in realtà, per essere normal è necessario che l'utente abbia fatto ALMENO 3 accessi (uno per ogni mese negli ultimi tre) quindi
count(distinct [Data Login]) > 2 AND count(distinct[DataLogin]) <= 10
Hai provato se funziona?
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
gio 27 apr 2006 - 17:24
Mi dà errore di sintassi perchè dice che la colonna [Data Login] dovrebbe comparire anche nella GROUP BY :(
La qual cosa mi sembra piuttosto improbabile: finchè la query è una
SELECT
CASE
WHEN count(distinct [Data Login]) > 5 THEN 'Normal'
Va tutto bene e non la vuole nella group by. Quando invece la trasformo in quanto scritto sopra, mi dice che la colonna [Data Login] è invalida perchè non compare nella Group By O_o
Ma se metto anche la data nella group by mi sballa tutto... e poi non dovrebbe servirmi metterlo... possibile che inserendo il
SELECT
CASE WHEN count(distinct DataLogin) > 5 AND DataLogin BETWEEN @DataInizio-30 AND @DataInizio AND count(distinct DataLogin) >2 THEN 'Normal'
Voglia la data login anche nella group by? E' un errore fake che ne nasconde un altro o sbaglio qualcosa io?
escaflowne
Profilo
| Junior Member
180
messaggi | Data Invio:
gio 27 apr 2006 - 17:41
......
>SELECT
>CASE WHEN count(distinct DataLogin) > 5 AND DataLogin BETWEEN
>@DataInizio-30 AND @DataInizio AND count(distinct DataLogin)
>>2 THEN 'Normal'
......
intanto metti un po' di parentesi, meglio abbondare che deficere ;)
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
gio 27 apr 2006 - 17:50
Lì ho scritto la versione semplificata, quella completa è:
FUNZIONANTE:
------------------
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'
WHEN count(distinct [Data Login]) > 0 AND count(distinct [Data Login]) <= 12 THEN '3.Occasionale'
END
ERRORE SUL GROUP BY:
------------------------------
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
AND (([Data Login] BETWEEN DATEADD(day, -15, @DataInizio) AND @DataInizio) AND (count(distinct [Data Login]) > 2))
AND (([Data Login] BETWEEN DATEADD(day, -30, @DataInizio) AND DATEADD(day, -15, @DataInizio)) AND (count(distinct [Data Login]) > 2))
AND (([Data Login] BETWEEN DATEADD(day, -45, @DataInizio) AND DATEADD(day, -30, @DataInizio)) AND (count(distinct [Data Login]) > 2))
THEN '4.Normal'
WHEN count(distinct [Data Login]) > 0 AND count(distinct [Data Login]) <= 12 THEN '3.Occasionale'
END
escaflowne
Profilo
| Junior Member
180
messaggi | Data Invio:
gio 27 apr 2006 - 18:05
>
>ERRORE SUL GROUP BY:
>------------------------------
>
>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
> AND (([Data Login] BETWEEN DATEADD(day, -15, @DataInizio) AND
>@DataInizio) AND (count(distinct [Data Login]) > 2))
> AND (([Data Login] BETWEEN DATEADD(day, -30, @DataInizio) AND
>DATEADD(day, -15, @DataInizio)) AND (count(distinct [Data Login])
>> 2))
> AND (([Data Login] BETWEEN DATEADD(day, -45, @DataInizio) AND
>DATEADD(day, -30, @DataInizio)) AND (count(distinct [Data Login])
>> 2))
>THEN '4.Normal'
>WHEN count(distinct [Data Login]) > 0 AND count(distinct [Data
>Login]) <= 12 THEN '3.Occasionale'
>END
Sembra, quindi, che il data Login presente nel between dia il problema.
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
ven 28 apr 2006 - 08:58
Già, e chissà perchè.... non capisco perchè, se lo metto lì, lo vuole anche nella GROUP BY, e se ci sia un modo per risolvere...
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
ven 28 apr 2006 - 15:59
Mi hanno dato una possibile prova di soluzione, e cioè implementare una logica 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
Purtroppo però, per provarla, dovrei inserirla nella stored procedure che mi avevano fornito tempo fa, e qui inizia il caos ^^"
Beh, per completezza ho postato in questo thread la proposta di soluzione, per il resto, visto che ora il problema è con la stored procedure, la discussione di come implementarla al suo interno l'ho continuata qui:
http://www.dotnethell.it/forum/messages.aspx?ThreadID=6915
che mi sembra più appropriato come thread... Se qualcuno però avesse soluzioni alternative ben venga ^^"
Hamelin [FL]
Profilo
| Junior Member
65
messaggi | Data Invio:
gio 4 mag 2006 - 10:50
Mi è stato detto che l'errore è dovuto al fatto che nella seconda query utilizzo DataLogin senza operatori di raggruppamento, e questo non è concesso, a meno di non riportare DataLogin nella clausola "GROUP BY" (cosa che, però, andrebbe contro la semantica dell'interrogazione).
Mi hanno fornito una soluzione alternativa, la seguente:
SELECT UserId,count(distinct DataLogin) AS Conteggio,
CASE
WHEN count(distinct DataLogin) > 48 THEN '5.Super'
WHEN count(distinct DataLogin) > 12
AND count(distinct DataLogin) <= 48
AND (((select DataLogin from TabellaLogin where DataLogin BETWEEN '01/01/2006' AND '01/04/2006') BETWEEN DATEADD(day, -15, @DataInizio) AND @DataInizio ) AND ( count(distinct DataLogin) > 2 ) )
AND (((select DataLogin from TabellaLogin where DataLogin BETWEEN '01/01/2006' AND '01/04/2006') BETWEEN DATEADD(day, -30, @DataInizio) AND DATEADD(day, -15, @DataInizio)) AND (count(distinct DataLogin) > 2))
AND (((select DataLogin from TabellaLogin where DataLogin BETWEEN '01/01/2006' AND '01/04/2006') BETWEEN DATEADD(day, -45, @DataInizio) AND DATEADD(day, -30, @DataInizio)) AND (count(distinct DataLogin) > 2))
THEN '4.Normal'
ELSE '3.Occasionale'
END AS Tipo
FROM TabellaLogin
WHERE DataLogin BETWEEN '01/01/2006' AND '01/04/2006'
GROUP BY UserId
La quale, però, mi dà il seguente errore:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression
Penso sia dovuto al fatto che stiamo dicendo
CASE WHEN SELECT DataLogin
che non gli piace molto... a logica, direi che si dovrebbe trasformare in qualcosa tipo
CASE WHEN ... AND count(((select DataLogin from TabellaLogin where DataLogin BETWEEN '01/01/2006' AND '01/04/2006') BETWEEN DATEADD(day, -15, @DataInizio) AND @DataInizio )) > 2 ]
Qualcuno avrebbe qualche idea di come poter rendere questa cosa in modo da utilizzare questa metodologia?
Grazie ancora per l'attenzione
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 !