2016-07-29 17 views
3

ich SQLServer bin mit 2012, und ich habe eine Tabelle timestamped wie folgt aus:Aufzeichnungen finden in einem Zeitraum von 24 Stunden (nicht vor allem die letzten 24 Stunden) erstellt

Id   INT  NOT NULL, --PK 
IdUser  INT  NOT NULL --FK from table USER 
-- Some other fields 
CreationDate DATETIME NOT NULL 

Diese Tabelle irgendeine Art von Aktion durch die gemacht aufzeichnet Benutzer.
Ich versuche zu finden IF ein Benutzer hat diese Art von Aktion mehr als 20 Mal (dh es gibt 20 Datensätze mit der gleichen IdUser in dieser Tabelle) in einem Zeitraum von 24 Stunden.

Das Problem ist, ich bin nicht die Datensätze in den letzten 24 Stunden abzurufen versucht, aber die Datensätze in einem Zeitraum von 24 Stunden (ab dem ersten Rekord bis heute)

Das ist, was ich schrieb :

SELECT IdUser 
FROM MyTable 
WHERE IdUser = 1 
    AND CreationDate BETWEEN DATEADD(day, -1, GETDATE()) AND GETDATE() -- <= WRONG 

Aber die WHERE Klausel meiner Bedürfnisse nicht paßt, da ich keine Ahnung, wie zu übersetzen "20 Datensätze aus der Benutzer-ID = 1 in einem Zeitraum von 24 Stunden zu suchen, nicht vor allem der letzten 24 Stunden "in SQL

BEISPIEL
Angenommen, unsere Benutzer-ID = 1 hat 154 Mal diese Aktion ausgeführt. Also habe ich 154 Datensätze in meiner Tabelle mit der Datetime des Datensatzes.

IdUser = 1 ; CreationDate = 2016-07-29 12:24:54.590 
IdUser = 1 ; CreationDate = 2016-07-29 16:51:55.856 
IdUser = 1 ; CreationDate = 2016-07-27 14:12:36.125 
(151 omitted rows) 

Was ich suche ist, wenn ich 20 Datensätze in einem Zeitraum von 24 Stunden für einen bestimmten Benutzer finden kann. In diesem Beispiel sind nur die ersten 2 Stunden in einem Zeitraum von 24 Stunden. In meinem Fall suche ich, ob es 20 oder mehr Datensätze in diesem Zeitraum gibt.

Könnte mir jemand helfen?
Danke

+0

Wenn Sie wissen, wie DATEADD verwenden (), warum benutzt du es nicht, um 24 Stunden anstatt 1 Tag zu bekommen? –

+1

Verwenden Sie einfach GROUP BY IdUser HAVING COUNT (CreationDate)> 20, um Benutzer mit mindestens 20 Aktionen zu erhalten.In Bezug auf das Datum können Sie die gleiche dateadd Funktion verwenden, indem Sie das Start- oder Enddatum/die Zeit als Parameter übergeben. –

+0

@RamGrandhi Ich weiß nicht, ob dies das gewünschte Ergebnis ergibt, weil seine "Gruppe" _alle_ 24 Stunden sein könnte. –

Antwort

6

eine ziemlich schmerzhafte Art und Weise, dies zu tun (Performance-weise) ist mit einem join/group by oder apply Betreibern.

Die apply sollte aus Sicht der Leistung besser sein:

select t.* 
from t cross apply 
    (select count(*) as cnt 
     from t t2 
     where t2.iduser = t.iduser and 
      t2.creationdate >= t.creationdate and 
      t2.creationdate < dateadd(day, 1, t.creationdate) 
    ) t24 
where t24.cnt >= 20; 

Ein Index für (iduser, creationdate) ist ein Gewinn für diese Abfrage.

+0

schlagen Sie mich auf den Schlag :) – gofr1

+0

Ich werde Ihre Antwort in Betracht ziehen, aber ich gebe zu, dass ich nie Kreuz anwenden, also werde ich über diese Schlüsselwörter lernen. Diese Abfrage wird jedoch in LINQ transformiert, also nicht sicher, dass die Optimierung nicht von LINQ "überschrieben" wird ... – AlexB

0

Haben Sie versucht, eine DateTime-Variable zu deklarieren und das Datum festzulegen, das Sie abfragen möchten?

Wenn Sie nur 'n' Datensätze wünschen, können Sie die TOP 'n' CLAUSE verwenden. Sogar, Sie können TOP n% verwenden, um einen Prozentsatz zu erhalten. (By the way, ist TOP zur Verfügung, beginnend mit SQLServer 2008)

DECLARE @DATE DATETIME = '20160601' --YYYYMMDD 

SELECT TOP 20 IdUser 
FROM MyTable 
WHERE IdUser = 1 
    AND CreationDate BETWEEN DATEADD(day, -1, @DATE) AND @DATE 
0

Sie den Wert für die @starttime passieren kann als

benötigt

DECLARE @starttime DATETIME SELECT IdUser FROM MyTable WHERE CreationDate BETWEEN @starttime and DATEADD(HOUR, 24, @starttime) GROUP BY IdUser HAVING COUNT(CreationDate) > 20

0
 --This will count all records occurring 24 hours after the first instance of a record 
SELECT t1.IdUser, T1.CreationDate, COUNT(0) AS InstancesIn24Hrs 
FROM MyTable t1 
JOIN MyTable t2 ON T1.IdUser = T2.IdUser AND t2.CreationDate 
        BETWEEN t1.CreationDate 
           AND 
          DATEADD(day, 1, t1.CreationDate) 
WHERE t1.IdUser = 1 
    GROUP BY t1.IdUser, T1.CreationDate 
    ORDER BY T1.CreationDate 
Verwandte Themen