web-dev-qa-db-fra.com

MS SQL Server "entre" inclut-il les limites de la plage?

Par exemple peut

SELECT foo
FROM bar
WHERE foo BETWEEN 5 AND 10

sélectionnez 5 et 10 ou ils sont exclus de la gamme?

224
Lea Verou

L'opérateur BETWEEN est inclusif.

De la documentation en ligne:

BETWEEN renvoie VRAI si la valeur de test_expression est supérieure ou égale à la valeur de begin_expression et inférieure ou égale à la valeur de end_expression.

DateTime Caveat

NB: Avec DateTimes, il faut faire attention. si seule une date est donnée, la valeur est prise à minuit ce jour-là; pour éviter les heures manquantes dans votre date de fin ou pour répéter la saisie des données du jour suivant à minuit dans plusieurs plages, votre date de fin doit être 3 millisecondes avant minuit le jour suivant votre date de fin. 3 millisecondes car moins que cela et la valeur sera arrondie à minuit le lendemain.

par exemple. pour obtenir toutes les valeurs d'ici juin 2016, vous devez exécuter:

where myDateTime between '20160601' and DATEADD(millisecond, -3, '20160701')

c'est à dire.

where myDateTime between '20160601 00:00:00.000' and '20160630 23:59:59.997'

datetime2 et datetimeoffset

Soustraire 3 ms à une date vous rendra vulnérable aux lignes manquantes dans la fenêtre 3 ms. La solution correcte est aussi la plus simple:

where myDateTime >= '20160601' AND myDateTime < '20160701'
250
DJ.

Oui, mais soyez prudent lorsque vous utilisez entre des dates.

BETWEEN '20090101' AND '20090131'

est vraiment interprété comme 12h, ou

BETWEEN '20090101 00:00:00' AND '20090131 00:00:00'

tout ce qui s’est passé pendant la journée du 31 janvier va donc manquer. Dans ce cas, vous devrez utiliser:

myDate >= '20090101 00:00:00' AND myDate < '20090201 00:00:00'  --CORRECT!

ou

BETWEEN '20090101 00:00:00' AND '20090131 23:59:59' --WRONG! (see update!)

UPDATE: Il est tout à fait possible de créer des enregistrements dans la dernière seconde de la journée, avec une date/heure aussi tard que 20090101 23:59:59.997! !

Pour cette raison, l’approche BETWEEN (firstday) AND (lastday 23:59:59) n’est pas recommandée.

Utilisez plutôt l'approche myDate >= (firstday) AND myDate < (Lastday+1).

Bon article sur cette question ici .

250
BradC

Exemple concret tiré de SQL Server 2008.

Données source:

ID    Start
1     2010-04-30 00:00:01.000
2     2010-04-02 00:00:00.000
3     2010-05-01 00:00:00.000
4     2010-07-31 00:00:00.000

Requete:

SELECT
    *
FROM
    tbl
WHERE
    Start BETWEEN '2010-04-01 00:00:00' AND '2010-05-01 00:00:00'

Résultats:

ID    Start
1     2010-04-30 00:00:01.000
2     2010-04-02 00:00:00.000

alt text

16
Ryan Rodemoyer

si vous appuyez sur ceci et que vous ne voulez pas vraiment essayer d'ajouter un jour dans le code, laissez la base de données le faire ..

myDate >= '20090101 00:00:00' AND myDate < DATEADD(day,1,'20090101 00:00:00')

Si vous incluez la partie heure: assurez-vous qu'elle mentionne minuit. Sinon, vous pouvez simplement omettre l'heure:

myDate >= '20090101' AND myDate < DATEADD(day,1,'20090101')

et ne vous inquiétez pas pour ça.

13
Shaun

ENTRE (Transact-SQL)

Spécifie une plage ( n ) ( inclus ) à tester.

test_expression [ NOT ] BETWEEN begin_expression AND end_expression

Arguments

test_expression

Expression à tester dans la plage définie par begin_expression et end_expression. expression_test doit avoir le même type de données que expression_baie et expression_end.

NOT

Spécifie que le résultat du prédicat doit être annulé.

begin_expression

Est-ce une expression valide. begin_expression doit être du même type de données que test_expression et end_expression.

end_expression

Est-ce une expression valide. end_expression doit être du même type de données que test_expression et begin_expression.

AND

Agit comme un espace réservé qui indique que expression_test doit être dans la plage indiquée par begin_expression et end_expression.

Remarques

Pour spécifier une plage exclusive, utilisez les opérateurs supérieur à (>) et inférieur à (<). Si l'une des entrées du prédicat BETWEEN ou NOT BETWEEN est NULL, le résultat est UNKNOWN.

Valeur du résultat

BETWEEN renvoie VRAI si la valeur de test_expression est supérieure ou égale à la valeur de begin_expression et inférieure ou égale à la valeur de end_expression.

NOT BETWEEN renvoie VRAI si la valeur de expression_test est inférieure à la valeur de expression_bug ou supérieure à la valeur de expression_dest.

12
Russ Cam

Si le type de données de la colonne est datetime, vous pouvez procéder comme suit pour éliminer l'heure de datetime et comparer uniquement les plages de dates.

where cast(getdate() as date) between cast(loginTime as date) and cast(logoutTime as date)
3
Kahlil Vanz

Cela inclut les limites.

declare @startDate date = cast('15-NOV-2016' as date) 
declare @endDate date = cast('30-NOV-2016' as date)
create table #test (c1 date)
insert into #test values(cast('15-NOV-2016' as date))
insert into #test values(cast('20-NOV-2016' as date))
insert into #test values(cast('30-NOV-2016' as date))
select * from #test where c1 between @startDate and @endDate
drop table #test
RESULT    c1
2016-11-15
2016-11-20
2016-11-30


declare @r1 int  = 10
declare @r2 int  = 15
create table #test1 (c1 int)
insert into #test1 values(10)
insert into #test1 values(15)
insert into #test1 values(11)
select * from #test1 where c1 between @r1 and @r2
drop table #test1
RESULT c1
10
11
15
0
Halim