J'essaie de comparer le temps dans un champ datetime dans une requête SQL, mais je ne sais pas si c'est vrai. Je ne veux pas comparer la partie date, mais seulement la partie heure.
Je fais ça:
SELECT timeEvent
FROM tbEvents
WHERE convert(datetime, startHour, 8) >= convert(datetime, @startHour, 8)
Est-ce correct?
Je pose la question parce que j’ai besoin de savoir si 08:00:00
est inférieur ou supérieur à 07:30:00
et je ne veux pas comparer la date, mais simplement la partie heure .
Merci!
Votre comparaison fonctionnera, mais elle sera lente car les dates sont converties en chaîne pour chaque ligne. Pour comparer efficacement deux heures, essayez:
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
Explication longue: une date sur le serveur SQL est stockée sous forme de nombre à virgule flottante. Les chiffres avant le point décimal représentent la date. Les chiffres après le point décimal représentent l'heure.
Alors voici un exemple de date:
declare @mydate datetime
set @mydate = '2009-04-30 19:47:16.123'
Convertissons-le en float:
declare @myfloat float
set @myfloat = cast(@mydate as float)
select @myfloat
-- Shows 39931,8244921682
Prenez maintenant la partie après le chiffre, c’est-à-dire le temps:
set @myfloat = @myfloat - floor(@myfloat)
select @myfloat
-- Shows 0,824492168212601
Reconvertissez-le en date/heure:
declare @mytime datetime
set @mytime = convert(datetime,@myfloat)
select @mytime
-- Shows 1900-01-01 19:47:16.123
Le 1900-01-01 n'est que la date "zéro"; vous pouvez afficher la partie heure avec convert, en spécifiant par exemple le format 108, qui est simplement l'heure:
select convert(varchar(32),@mytime,108)
-- Shows 19:47:16
Les conversions entre date/heure et float sont assez rapides, car elles sont stockées de la même manière.
convert(varchar(5), thedate, 108) between @leftTime and @rightTime
Explication:
si vous avez varchar(5)
vous obtiendrez HH:mm
si vous avez varchar(8)
vous obtenez HH:mm ss
108 n'obtient que l'heure à partir de la date SQL
@leftTime
et @rightTime
sont deux variables à comparer
Si vous utilisez SQL Server 2008, vous pouvez procéder comme suit:
WHERE CONVERT(time(0), startHour) >= CONVERT(time(0), @startTime)
Voici un test complet:
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)
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))
L'utilisation de float ne fonctionne pas.
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))
Vous verrez que les valeurs ne sont pas les mêmes (SQL Server 2005). Je voulais utiliser cette méthode pour vérifier les heures autour de minuit (la méthode complète contient plus de détails) pour laquelle je comparais l'heure actuelle entre 23h55 et 00h05.
Il suffit de modifier convert datetime en time qui devrait faire l'affaire:
SELECT timeEvent
FROM tbEvents
WHERE convert(time, startHour) >= convert(time, @startHour)
Un problème (peut-être mineur) que j'ai noté avec les solutions jusqu'ici est qu'elles semblent toutes nécessiter un appel de fonction pour traiter la comparaison. Cela signifie que le moteur de requête devra effectuer une analyse complète de la table pour rechercher les lignes que vous recherchez, sans pouvoir utiliser d'index. Si la table ne devient pas particulièrement grande, cela n'aura probablement aucun effet négatif (et vous pouvez volontiers ignorer cette réponse).
Si, au contraire, la table pouvait devenir assez grande, les performances de la requête pourraient en souffrir.
Je sais que vous avez indiqué que vous ne souhaitiez pas comparer la partie de la date - mais y a-t-il une date réelle stockée dans la colonne date/heure ou l'utilisez-vous pour stocker uniquement l'heure? Dans ce dernier cas, vous pouvez utiliser un simple opérateur de comparaison, ce qui réduira l'utilisation du processeur et permettra au moteur de requête d'utiliser des statistiques et des index (le cas échéant) pour optimiser la requête.
Si, toutefois, la colonne datetime est utilisée pour stocker à la fois la date et l'heure de l'événement, cela ne fonctionnera évidemment pas. Dans ce cas, si vous pouvez modifier l’application et la structure de la table, séparer la date et l’heure en deux colonnes datetime distinctes, ou créer une vue indexée qui sélectionne toutes les colonnes (pertinentes) de la table source et élément temporel que vous souhaitez rechercher (utilisez l’une des réponses précédentes pour le calculer) et modifiez l’application pour interroger la vue.
Utiliser la fonction Datepart: DATEPART (datepart, date)
Par exemple#
SELECT DatePart (@YourVar, hh) * 60) + DatePart (@YourVar, mi) * 60)
Cela vous donnera le temps total de la journée en minutes vous permettant de comparer plus facilement.
Vous pouvez utiliser DateDiff si vos dates sont identiques, sinon vous devrez supprimer la date ci-dessus.
Ajouter aux autres réponses:
vous pouvez créer une fonction pour rogner la date à partir d'un datetime
CREATE FUNCTION dbo.f_trimdate (@dat datetime) RETURNS DATETIME AS BEGIN
RETURN CONVERT(DATETIME, CONVERT(FLOAT, @dat) - CONVERT(INT, @dat))
END
Donc ça:
DECLARE @dat DATETIME
SELECT @dat = '20080201 02:25:46.000'
SELECT dbo.f_trimdate(@dat)
Je reviendrai 1900-01-01 02: 25: 46.000
SELECT timeEvent
FROM tbEvents
WHERE CONVERT(VARCHAR,startHour,108) >= '01:01:01'
Cela indique à SQL Server de convertir la date et l'heure actuelles en varchar en utilisant le style 108, qui est "hh: mm: ss". Vous pouvez également remplacer "01: 01: 01" qu'un autre convertisseur convertira si nécessaire.
Je crois que vous voulez utiliser DATEPART('hour', datetime)
.
La référence est ici:
Je n'aime pas utiliser des ressources internes de stockage (cette date-heure est un flottant avec un nombre entier = jour et une fraction = heure), mais je fais la même chose que la réponse Jhonny D. Cano. C’est ainsi que tous les développeurs de base de données que je connais le font. Certainement pas convertir en chaîne. Si vous devez éviter le traitement en tant que float/int, la meilleure option consiste à extraire heure/minute/seconde/millisecondes avec DatePart ().
Vous pouvez créer deux variables datetime et définir uniquement l'heure de la date à comparer.
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)
La date sera "1900-01-01" vous pouvez le comparer
if @date1 <= @date2
print '@date1 less then @date2'
else
print '@date1 more then @date2'
Je suppose que votre colonne startHour et votre variable @startHour sont toutes deux DATETIME; Dans ce cas, vous devriez convertir en chaîne:
SELECT timeEvent
FROM tbEvents
WHERE convert(VARCHAR(8), startHour, 8) >= convert(VARCHAR(8), @startHour, 8)
@ronmurp soulève une préoccupation valable: l'approche cast/floor renvoie différentes valeurs pour le même temps. Dans le sens de la réponse de @littlechris et d’une solution plus générale permettant de résoudre les moments comportant un composant minute, secondes, millisecondes, vous pouvez utiliser cette fonction pour compter le nombre de millisecondes à partir du début de la journée.
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
J'ai vérifié qu'il renvoie le même int pour deux dates différentes avec le même temps
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 )
Cette solution ne retourne pas toujours le int que vous attendez. Par exemple, essayez ce qui suit dans SQL 2005, il retourne un int se terminant par '557' au lieu de '556'.
set @first = '1900-01-01 23:59:39.556'
set @second = '2000-11-02 23:56:39.556'
Je pense que cela a à voir avec la nature de DateTime stockée en tant que float. Vous pouvez toujours comparer les deux nombres, cependant. Et quand j'ai utilisé cette approche sur un "réel" jeu de données de DateTime capturé dans .NET à l'aide de DateTime.Now () et stocké en SQL, j'ai constaté que les calculs étaient précis.
requête ci-dessous vous donne l'heure de la date
select DateAdd(day,-DateDiff(day,0,YourDateTime),YourDateTime) As NewTime from Table