2010-03-26 10 views
2

Mon algorithme est pour un 'compteur de hits', j'essaie de ne pas compter deux fois la même personne si cette personne est venue deux fois sur le site intervalle de temps (par exemple, s'il vient deux fois en 5 minutes, je veux compter comme 1 succès pour cette personne)J'ai besoin de quelques idées sur mon algorithme pour un compteur de hits (Group By Time Interval)

Voici ce que ma base de données ressemble

UserIp  UserId   Date of user came 
127.0.0.1 new.user.akb 26.03.2010 10:15:44 
127.0.0.1 new.user.akb 26.03.2010 10:16:44 
127.0.0.1 new.user.akb 26.03.2010 10:17:44 
127.0.0.1 new.user.akb 26.03.2010 10:18:44 
127.0.0.1 new.user.akb 26.03.2010 10:19:44 
127.0.0.1 new.user.akb 26.03.2010 10:20:44 
127.0.0.1 new.user.akb 26.03.2010 10:21:44 
127.0.0.1 new.user.akb 26.03.2010 10:22:44 
127.0.0.1 new.user.akb 26.03.2010 10:23:44 

ce que je dois faire est d'obtenir le numéro de UserIP distincts de la table ci-dessus qui s'est produite dans un intervalle de temps. Par exemple, si je mets l'intervalle de temps pendant 5 minutes, et disons qu'il commence à

26.03.2010 10:15:44 

Ensuite, je vais obtenir 2 que les résultats, car il y a une valeur distincte entre 10:15-10:20 et , 1 autre valeur distincte 10h20-10h23,

Par exemple, si mon intervalle est de 3 minutes que le résultat de retour sera 3

+0

Êtes-vous plus intéressé par un sql ou C# solution? –

+0

Sql solution serait mieux pour moi. – stckvrflw

+0

J'ai décidé d'ajouter une solution linq en C# à ma réponse. –

Répondre

4

Il y a une question presque identique ici: Group by Time interval.

le bases de c'est que vous devez grouper par t Il intervalle de temps en appliquant un plancher à la date-heure pour aplatir l'intervalle.

EDIT

a résolu le problème en utilisant groupement:

SET DATEFORMAT dmy; 

DECLARE @table TABLE 
(
    UserIp nvarchar(15), 
    UserId nvarchar(15), 
    VisitDate datetime 
) 

INSERT INTO @table 
VALUES ('127.0.0.1', 'new.user.akb', '26.03.2010 10:15:44') 
     ,('127.0.0.1', 'new.user.akb', '26.03.2010 10:16:44') 
     ,('127.0.0.1', 'new.user.akb', '26.03.2010 10:17:44') 
     ,('127.0.0.1', 'new.user.akb', '26.03.2010 10:18:44') 
     ,('127.0.0.1', 'new.user.akb', '26.03.2010 10:19:44') 
     ,('127.0.0.1', 'new.user.akb', '26.03.2010 10:20:44') 
     ,('127.0.0.1', 'new.user.akb', '26.03.2010 10:21:44') 
     ,('127.0.0.1', 'new.user.akb', '26.03.2010 10:22:44') 
     ,('127.0.0.1', 'new.user.akb', '26.03.2010 10:23:44') 


SELECT UserIp, UserId, MIN(VisitDate) AS firstVisit 
FROM @table 
GROUP BY dateadd(mi, (datepart(mi,VisitDate)/5)*5, 
      dateadd(hh, datediff(hh,0,VisitDate),0)), 
     UserIp, UserId 

Cela donne le résultat suivant (mon format de date est AMJ):

UserIp   UserId   firstVisit 
--------------- --------------- ----------------------- 
127.0.0.1  new.user.akb 2010-03-26 10:15:44.000 
127.0.0.1  new.user.akb 2010-03-26 10:20:44.000 

(2 row(s) affected) 

Ce qui signifie que vous pouvez compter sur ce jeu de résultats pour un nombre de visites par 5min.

3

20000101 est un peu startdate:

select dateadd(mi, -d, '20000101') as d, num from 
(select count(*) num, datediff(mi ,date_field, '20000101')/5 * 5 d 
from your_table 
group by datediff(mi, date_field, '20000101')/5 * 5) as a 
order by d 

Et voici une solution de C# en utilisant Linq:

var d1 = new Tuple<string, string, DateTime>("127.0.0.1", "new.user.akb", DateTime.Parse("26.03.2010 10:15:44")); 
var d2 = new Tuple<string, string, DateTime>("127.0.0.1", "new.user.akb", DateTime.Parse("26.03.2010 10:16:44")); 
var d3 = new Tuple<string, string, DateTime>("127.0.0.1", "new.user.akb", DateTime.Parse("26.03.2010 10:17:44")); 
var d4 = new Tuple<string, string, DateTime>("127.0.0.1", "new.user.akb", DateTime.Parse("26.03.2010 10:18:44")); 
var d5 = new Tuple<string, string, DateTime>("127.0.0.1", "new.user.akb", DateTime.Parse("26.03.2010 10:19:44")); 
var d6 = new Tuple<string, string, DateTime>("127.0.0.1", "new.user.akb", DateTime.Parse("26.03.2010 10:20:44")); 
var d7 = new Tuple<string, string, DateTime>("127.0.0.1", "new.user.akb", DateTime.Parse("26.03.2010 10:21:44")); 
var d8 = new Tuple<string, string, DateTime>("127.0.0.1", "new.user.akb", DateTime.Parse("26.03.2010 10:22:44")); 
var d9 = new Tuple<string, string, DateTime>("127.0.0.1", "new.user.akb", DateTime.Parse("26.03.2010 10:23:44")); 
var list = new List<Tuple<string, string, DateTime>> {d1, d2, d3, d4, d5, d6, d7, d8, d9}; 

int interval = 3; 
var query = list.GroupBy(data => ((int) (DateTime.Now - data.Item3).TotalMinutes)/interval*interval) 
    .Select(data => new {IP = data.First().Item1}); 

foreach (var entry in query) 
{ 
    Console.WriteLine(entry.IP); 
} 
+0

+ 1, j'aime la version LINQ, et l'utilisation de la classe Tuple m'a fait sourire :) – Codesleuth