web-dev-qa-db-de.com

Wie kann ich die Zeit in SQL Server vergleichen?

Ich versuche, die Zeit in einem datetime-Feld in einer SQL-Abfrage zu vergleichen, aber ich weiß nicht, ob es richtig ist. Ich möchte den Datumsteil nicht vergleichen, nur den Zeitteil.

Ich mache das:

SELECT timeEvent 
FROM tbEvents 
WHERE convert(datetime, startHour, 8) >= convert(datetime, @startHour, 8)

Ist es richtig? 

Ich frage das, weil ich wissen muss, ob 08:00:00 kleiner oder größer als 07:30:00 ist und ich das Datum nicht vergleichen möchte, nur den timepart.

Vielen Dank!

54
AndreMiranda

Ihr Vergleich wird funktionieren, wird aber langsam sein, da die Datumsangaben für jede Zeile in einen String umgewandelt werden. Um zwei Zeitbereiche effizient zu vergleichen, versuchen Sie Folgendes:

declare @first datetime
set @first = '2009-04-30 19:47:16.123'
declare @second datetime
set @second = '2009-04-10 19:47:16.123'

select (cast(@first as float) - floor(cast(@first as float))) -
       (cast(@second as float) - floor(cast(@second as float)))
       as Difference

Lange Erklärung: Ein Datum im SQL Server wird als Fließkommazahl gespeichert. Die Ziffern vor dem Komma stehen für das Datum. Die Nachkommastellen geben die Uhrzeit an.

Also hier ein Beispieldatum:

declare @mydate datetime
set @mydate = '2009-04-30 19:47:16.123'

Lassen Sie uns es in einen Float umwandeln:

declare @myfloat float
set @myfloat = cast(@mydate as float)
select @myfloat
-- Shows 39931,8244921682

Nimm jetzt den Teil nach der Ziffer, also die Uhrzeit:

set @myfloat = @myfloat - floor(@myfloat) 
select @myfloat
-- Shows 0,824492168212601

Konvertiere es zurück in eine Datumszeit:

declare @mytime datetime
set @mytime = convert(datetime,@myfloat)
select @mytime
-- Shows 1900-01-01 19:47:16.123

Der 1900-01-01 ist nur das "Nulldatum"; Sie können den Zeitabschnitt mit convert anzeigen. Geben Sie beispielsweise das Format 108 an. Dies ist nur die Uhrzeit:

select convert(varchar(32),@mytime,108)
-- Shows 19:47:16

Konvertierungen zwischen datetime und float sind ziemlich schnell, da sie grundsätzlich auf dieselbe Weise gespeichert werden.

74
Andomar
convert(varchar(5), thedate, 108) between @leftTime and @rightTime

Erläuterung:

wenn Sie varchar(5) haben, erhalten Sie HH:mm

wenn Sie varchar(8) haben, erhalten Sie HH:mm ss

108 erhält nur die Zeit vom SQL-Datum

@leftTime und @rightTime sind zwei zu vergleichende Variablen

18
Iralda Mitro

Wenn Sie SQL Server 2008 verwenden, können Sie Folgendes tun:

WHERE CONVERT(time(0), startHour) >= CONVERT(time(0), @startTime)

Hier ist ein voller Test:

DECLARE @tbEvents TABLE (
    timeEvent   int      IDENTITY,
    startHour   datetime
)

INSERT INTO @tbEvents (startHour) SELECT DATEADD(hh, 0, GETDATE())
INSERT INTO @tbEvents (startHour) SELECT DATEADD(hh, 1, GETDATE())
INSERT INTO @tbEvents (startHour) SELECT DATEADD(hh, 2, GETDATE())
INSERT INTO @tbEvents (startHour) SELECT DATEADD(hh, 3, GETDATE())
INSERT INTO @tbEvents (startHour) SELECT DATEADD(hh, 4, GETDATE())
INSERT INTO @tbEvents (startHour) SELECT DATEADD(hh, 5, GETDATE())

--SELECT * FROM @tbEvents

DECLARE @startTime  datetime

SET @startTime = DATEADD(mi, 65, GETDATE())

SELECT
    timeEvent,
    CONVERT(time(0), startHour)  AS 'startHour',
    CONVERT(time(0), @startTime) AS '@startTime'
FROM @tbEvents
WHERE CONVERT(time(0), startHour) >= CONVERT(time(0), @startTime)
11
Rob Garrison
if (cast('2012-06-20 23:49:14.363' as time) between 
    cast('2012-06-20 23:49:14.363' as time) and 
    cast('2012-06-20 23:49:14.363' as time))
4
Edgardo Correa

Die Verwendung von Float funktioniert nicht.

DECLARE @t1 datetime, @t2 datetime
SELECT @t1 = '19000101 23:55:00', @t2 = '20001102 23:55:00'
SELECT CAST(@t1 as float) - floor(CAST(@t1 as float)), CAST(@t2 as float) - floor(CAST(@t2 as float))

Sie werden sehen, dass die Werte nicht identisch sind (SQL Server 2005). Ich wollte diese Methode verwenden, um nach Mitternacht zu suchen (die vollständige Methode enthält mehr Details), in der ich die aktuelle Zeit zwischen 23:55:00 und 00:05:00 verglich.

3
ronmurp

Ändern Sie einfach konvertieren Datumszeit in Zeit, die den Trick tun sollte:

SELECT timeEvent 
FROM tbEvents 
WHERE convert(time, startHour) >= convert(time, @startHour)
3
Yi Zhang

Ein (möglicherweise kleines) Problem, das ich bei den Lösungen bisher bemerkt habe, ist, dass sie alle einen Funktionsaufruf erfordern, um den Vergleich durchzuführen. Dies bedeutet, dass das Abfrage-Modul einen vollständigen Tabellenscan durchführen muss, um die Zeilen zu suchen, nach denen Sie suchen - und keinen Index verwenden können. Wenn die Tabelle nicht besonders groß wird, hat dies wahrscheinlich keine nachteiligen Auswirkungen (und Sie können diese Antwort gerne ignorieren).

Wenn die Tabelle andererseits ziemlich groß werden könnte, könnte die Leistung der Abfrage leiden.

Ich weiß, dass Sie angegeben haben, dass Sie den Datumsteil nicht vergleichen möchten - aber wird in der datetime-Spalte ein tatsächliches Datum gespeichert, oder verwenden Sie es, um nur die Uhrzeit zu speichern? In letzterem Fall können Sie einen einfachen Vergleichsoperator verwenden. Dadurch wird sowohl die CPU-Auslastung reduziert als auch das Abfrage-Modul die Möglichkeit haben, Statistiken und Indizes (falls vorhanden) zur Optimierung der Abfrage zu verwenden.

Wenn jedoch die datetime-Spalte zum Speichern von Datum und Uhrzeit des Ereignisses verwendet wird, funktioniert dies offensichtlich nicht. Wenn Sie in diesem Fall die App und die Tabellenstruktur ändern können, trennen Sie Datum und Uhrzeit in zwei separate datetime-Spalten oder erstellen Sie eine indizierte Sicht, in der alle (relevanten) Spalten der Quelltabelle ausgewählt werden, und eine weitere Spalte, die die Zeitelement, nach dem Sie suchen möchten (verwenden Sie eine der vorherigen Antworten, um dies zu berechnen) - und ändern Sie stattdessen die App, um die Ansicht abzufragen.

3
Jason Musgrove

Datepart-Funktion verwenden: DATEPART (datepart, date) 

Z.B#

SELECT DatePart (@YourVar, hh) * 60) + DatePart (@YourVar, mi) * 60)

Dadurch erhalten Sie die Gesamtzeit des Tages in Minuten, sodass Sie einfacher vergleichen können.

Sie können DateDiff verwenden, wenn Ihre Daten gleich sind. Andernfalls müssen Sie das Datum wie oben beschrieben entfernen

2
littlechris

Hinzufügen zu den anderen Antworten:

sie können eine Funktion zum Abgleichen des Datums aus einer Datumszeit erstellen

CREATE FUNCTION dbo.f_trimdate (@dat datetime) RETURNS DATETIME AS BEGIN
    RETURN CONVERT(DATETIME, CONVERT(FLOAT, @dat) - CONVERT(INT, @dat))
END

Also das:

DECLARE @dat DATETIME
SELECT @dat = '20080201 02:25:46.000'
SELECT dbo.f_trimdate(@dat)

Kehrt zurück 1900-01-01 02: 25: 46.000

SELECT timeEvent 
  FROM tbEvents 
 WHERE CONVERT(VARCHAR,startHour,108) >= '01:01:01'

Dadurch wird SQL Server angewiesen, das aktuelle Datum/die aktuelle Uhrzeit in einen Varchar unter Verwendung von Stil 108 zu konvertieren, der "hh: mm: ss" ist. Sie können auch '01: 01: 01 'ersetzen, um ggf. einen anderen zu konvertieren.

1
northpole

Ich glaube, Sie möchten DATEPART('hour', datetime) verwenden.

Referenz ist hier:

http://msdn.Microsoft.com/de-de/library/ms174420.aspx

1
Paul Sonier

Ich mag es nicht, auf interne Speicherinhalte angewiesen zu sein (datetime ist ein Float mit Ganzzahl = Tag und Bruchzeit = Zeit), aber ich tue dasselbe wie die Antwort Jhonny D. Cano. Auf diese Weise tun alle db-Entwickler, die ich kenne, dies. Konvertieren Sie auf keinen Fall in einen String. Wenn Sie die Verarbeitung als float/int vermeiden müssen, ist es am besten, mit DatePart () die Stunden/Minuten/Sekunden/Millisekunden herauszuziehen.

1
ahains

Sie können zwei Variablen von datetime erstellen und nur die Uhrzeit des Datums einstellen, die Sie vergleichen müssen.

declare  @date1 datetime;
declare  @date2 datetime;

select   @date1 = CONVERT(varchar(20),CONVERT(datetime, '2011-02-11 08:00:00'), 114)
select   @date2 = CONVERT(varchar(20),GETDATE(), 114)

Das Datum wird "1900-01-01" sein, Sie können es vergleichen

if @date1 <= @date2
   print '@date1 less then @date2'
else
   print '@date1 more then @date2'
1
Renato Bezerra

Ich gehe davon aus, dass Ihre startHour-Spalte und die @ startHour-Variable beide DATETIME sind. In diesem Fall sollten Sie in einen String konvertieren:

SELECT timeEvent
FROM tbEvents
WHERE convert(VARCHAR(8), startHour, 8) >= convert(VARCHAR(8), @startHour, 8)
0
Chris Shaffer

@ronmurp wirft ein gültiges Problem auf - der Cast/Floor-Ansatz gibt für die gleiche Zeit unterschiedliche Werte zurück. Im Sinne der Antwort von @littlechris und für eine allgemeinere Lösung, die nach einer Minute, Sekunden und Millisekunden-Komponente berechnet, können Sie mit dieser Funktion die Anzahl der Millisekunden ab dem Tagesbeginn zählen.

Create Function [dbo].[MsFromStartOfDay] ( @DateTime datetime )
Returns int
As
  Begin
      Return (
               ( Datepart( ms , @DateTime ) ) +
               ( Datepart( ss , @DateTime ) * 1000 ) +
               ( Datepart( mi , @DateTime ) * 1000 * 60 ) +
               ( Datepart( hh , @DateTime ) * 1000 * 60 * 60 )
              )
  End

Ich habe bestätigt, dass es das gleiche int für zwei verschiedene Datumsangaben zur selben Zeit zurückgibt

declare @first datetime
set @first = '1900-01-01 23:59:39.090'
declare @second datetime
set @second = '2000-11-02 23:56:39.090'
Select dbo.MsFromStartOfDay( @first )
Select dbo.MsFromStartOfDay( @second )

Diese Lösung gibt nicht immer das Intellekt zurück, das Sie erwarten würden. Versuchen Sie beispielsweise Folgendes in SQL 2005, es gibt ein int ', das auf' 557 'endet, statt' 556 '.

set @first = '1900-01-01 23:59:39.556'
set @second = '2000-11-02 23:56:39.556'

Ich denke, das hat mit der Natur von DateTime als Float zu tun. Sie können die beiden Zahlen jedoch immer noch vergleichen. Und als ich diesen Ansatz für eine "echte" Datenmenge von DateTime verwendet habe, die in .NET mit DateTime.Now () erfasst und in SQL gespeichert wurde, stellte ich fest, dass die Berechnungen korrekt waren.

0
SFun28

die folgende Abfrage gibt Ihnen die Uhrzeit an 

select DateAdd(day,-DateDiff(day,0,YourDateTime),YourDateTime) As NewTime from Table
0
Darsh