Database
 sql >> Base de données >  >> RDS >> Database

SQL BETWEEN-Conseils intelligents pour rechercher une plage de valeurs

SQL BETWEEN est un opérateur utilisé pour spécifier une plage de valeurs à tester. La valeur renvoyée peut être inclusive ou comprise dans la plage. Ou il peut être en dehors de la plage si vous ajoutez l'opérateur NOT avant. Cela fonctionne pour les dates, les dates avec l'heure, les nombres et les chaînes.

Vous pouvez l'utiliser sur les clauses WHERE pour les éléments suivants :

  • SÉLECTIONNER,
  • INSÉRER (avec SELECT)
  • MISE À JOUR,
  • et SUPPRIMER.

Cela fonctionne également pour les clauses HAVING avec GROUP BY.

Mais si vous ne faites pas attention, SQL BETWEEN peut vous rendre fou lors de son utilisation, en particulier avec les dates avec le temps.

Ne vous inquiétez pas, cependant. Nous avons des exemples pour traiter les pièges de l'utilisation de SQL BETWEEN. Mais avant cela, les exemples de données que j'ai utilisés provenaient de NOAA . Vous pouvez leur demander gratuitement des données météorologiques. J'ai utilisé les enregistrements de température horaires pour les États-Unis en 2010. Ensuite, j'ai importé les données CSV sur SQL Server à l'aide de SQL Server Management Studio. J'ai renommé les colonnes et ajouté un index non clusterisé.

Commençons.

Utilisation de SQL BETWEEN avec des dates et des heures

Il doit s'agir de l'élément le plus recherché lorsqu'il s'agit de SQL BETWEEN. Nous utiliserons des exemples pour expliquer comment cela fonctionne.

Astuce n° 1 :pour les colonnes DATETIME, spécifiez à la fois la date et l'heure

UTILISATION INCORRECTE

Commençons par le mauvais usage pour souligner ce point. L'utilisation suivante de BETWEEN avec des colonnes DATETIME donnera des résultats inattendus.


SELECT 
 DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour BETWEEN '01/01/2010' AND '01/02/2010'
AND Latitude = 41.995
AND Longitude = -87.9336;


La requête renvoie des données pendant 2 jours à partir d'une station météo près de l'aéroport international O'Hare de Chicago. Vous pouvez remarquer la plage entre une valeur inférieure (01/01/2010) et une valeur supérieure (01/02/2010). Voici le jeu de résultats de la figure 1.

Illustration 1 . Ensemble de résultats d'une requête utilisant SQL ENTRE 2 dates.

Mais où est le problème ?

C'est censé être un record horaire pendant 2 jours. Pour cette raison, le jeu de résultats doit contenir 48 enregistrements. Mais notez que ce n'est que 24. Le problème réside dans l'élément de temps de la DateHour colonne. Lorsque vous ne spécifiez pas l'heure dans une colonne DATETIME, elle suppose 00:00 ou 12:00 AM. Notez également que les données ont commencé le 1er janvier 2010 à 01h00 et non à 00h00.

Ainsi, en interne, SQL Server a utilisé DateHour ENTRE '01/01/2010 00:00:00.000′ ET '01/02/2010 00:00:00.000′ . Comment le savons-nous ?

LA DATE EST EN RÉALITÉ UNE CHAÎNE

C'est vrai.

Les valeurs de date entre guillemets simples ne sont pas vraiment des dates mais des chaînes . SQL Server utilise la conversion implicite pour convertir la chaîne en DATETIME. Après la conversion, la partie heure sera ajoutée à la date.

Inspectons avec Inclure le plan d'exécution réel . Appuyez sur Ctrl-M dans SQL Server Management Studio, puis relancez l'exemple précédent.

Lorsque le plan d'exécution apparaît, cliquez avec le bouton droit sur Index Seek opérateur et sélectionnez Propriétés . Voir Figure 2.

Illustration 2 . Conversion implicite d'une chaîne en DATETIME. Il est masqué dans le plan d'exécution d'une requête utilisant BETWEEN.

Développez ensuite le champ Rechercher les prédicats . Les parties encadrées de la figure 2 montrent la conversion implicite des 2 chaînes en DATETIME. Étant donné que la conversion implicite est effectuée en interne , les débutants se demandent pourquoi leurs attentes dans l'ensemble de résultats ne sont pas satisfaites.

UTILISATION CORRECTE

L'exemple ci-dessous renverra les enregistrements horaires entre 8h00 et 12h00 le 2 janvier 2010.


SELECT * FROM TemperatureData
WHERE DateHour BETWEEN '01/02/2010 08:00' AND '01/02/2010 12:00'
AND Latitude = 41.995
AND Longitude = -87.9336;


Vous devez spécifier la partie horaire, en particulier lorsque les dates sont identiques. Ou vos résultats attendus ne se produiront pas.

Pour renvoyer les enregistrements de toute la journée, cela ne fonctionnera pas :


SELECT 
 DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour = '06/01/2010'
AND Latitude = 41.995
AND Longitude = -87.9336;


Il ne renverra qu'un seul enregistrement - celui du 1er juin 2010 à 00h00. Mais en utilisant BETWEEN avec les heures spécifiées, vous pouvez renvoyer l'enregistrement de chaque heure pour toute la journée. Voir l'exemple suivant.


SELECT 
 DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour BETWEEN '06/01/2010 00:00' AND '06/01/2010 23:00'
AND Latitude = 41.995
AND Longitude = -87.9336;


Notez que j'ai spécifié jusqu'à 23h00 seulement. Si vos données utilisent n'importe quelle heure de la journée, utilisez 23h59 ou 23h59 dans la valeur la plus élevée de la plage. Spécifiez également les secondes si vous en avez besoin.

Conseil n° 2 :tenez compte du type de données DATE

Si vous n'avez pas besoin de la partie heure, considérez plutôt le type de données DATE. Et vous éviterez les problèmes mentionnés ci-dessus.

SQL ENTRE avec des nombres

Passons aux chiffres.

Astuce n° 3 :incluez la partie décimale pour les valeurs non entières


SELECT
 DateHour
,[Hourly_Heating_Degree_Hours]
FROM TemperatureData
WHERE DateHour BETWEEN '06/01/2010' AND '06/5/2010 23:00'
AND [Hourly_Heating_Degree_Hours] BETWEEN 5.0 AND 7.0
AND Latitude = 41.995
AND Longitude = -87.9336;


Notez l'ajout d'une autre condition impliquant des nombres. Les résultats seront en outre limités à 5 et 7 degrés.

Lorsque vous utilisez les types de données DECIMAL, MONEY ou FLOAT, spécifiez la partie décimale même si elle est nulle, comme 52,00 ou 10,0000. De cette façon, vous évitez la conversion implicite aux types de données cibles DECIMAL, MONEY ou FLOAT.

SQL ENTRE avec des chaînes

Astuce n°4 :Pour les chaînes, la plage est basée sur le classement

Avec les chaînes, BETWEEN évalue les valeurs en fonction de l'ordre alphabétique. ‘A’ est le plus petit et ‘Z’ est le plus grand. Vous pouvez également dire qu'en général, l'évaluation est basée sur la collation. Parce que l'anglais n'est pas la seule langue prise en charge par SQL Server. Collation fournit des règles de tri, une sensibilité à la casse et aux accents. Utilisons AdventureWorks base de données pour cet exemple. Consultez le code ci-dessous et le résultat de la figure 3.


USE AdventureWorks
GO

SELECT 
 LastName
,FirstName
,MiddleName
FROM Person.Person
WHERE Lastname BETWEEN 'Spanaway' AND 'Splane'
ORDER BY LastName;

Illustration 3 . Ensemble de résultats d'une requête utilisant BETWEEN avec des chaînes.

La gamme couvre le nom de famille Spanaway . Mais où est Splane ? Il est inexistant dans la base de données. Ainsi, le résultat n'a atteint que jusqu'à Spicer .

Conseils SQL BETWEEN pour tous les types de données pris en charge

Que vous utilisiez BETWEEN pour des dates, des nombres ou des chaînes, vous devez être conscient de certaines choses courantes. Cela pourrait être du bon sens, mais cela se produit toujours par erreur. Découvrez comment cela peut se produire.

Astuce n° 5 :les valeurs de début et de fin ne peuvent pas être NULL

BETWEEN nécessite des valeurs de début et de fin pour la plage. Chacun doit avoir une valeur qui n'est pas NULL. Il y a un exemple avec une valeur finale NULL ci-dessous.


SELECT 
 DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour BETWEEN '01/01/2010' AND NULL;


Cela peut se produire si vous appelez l'instruction SELECT à partir d'une application ou d'une procédure stockée et que vous ne l'avez pas validée correctement.

Astuce n°6 :La valeur de départ ne peut pas être supérieure à la valeur de fin

Rien ne sera également renvoyé si les deux valeurs ne sont pas NULL, mais la plage est inversée. Voici un exemple.

SELECT 
 DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour BETWEEN '01/30/2010' AND '01/01/2010';


Hormis les dates, les expressions suivantes ne renverront pas non plus de résultat :

  • valeur ENTRE 100 ET -200. Parce que -200 est inférieur à 100.
  • Travailler ENTRE "Gardien de zoo" ET "Comptable". Parce que 'Z' est supérieur à 'A'.

Astuce n° 7 :les valeurs de plage doivent être du même type de données

Parfois, les contrôles de l'interface utilisateur ont une sortie inattendue. Ou nous avons simplement choisi la mauvaise propriété. Et si nous ne le vérifions pas avant de le transmettre à SQL Server, une situation comme celle-ci peut se produire :


SELECT 
 DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour BETWEEN '06/01/2010' AND 'Saturday, June 5, 2010'
AND Latitude = 41.995
AND Longitude = -87.9336;

Une erreur de conversion d'une chaîne de caractères vers une date se produira.

Ainsi, la leçon de l'astuce n° 5 à n° 7 consiste à valider les valeurs de début et de fin de la plage .

Astuce n° 8 :utilisez NOT BETWEEN pour exclure des valeurs

Prenons un autre exemple.


SELECT
 MONTH(DateHour) AS [Month] 
,round(AVG([Hourly_Heating_Degree_Hours]),2) AS AverageTemperature
FROM TemperatureData
WHERE DateHour BETWEEN '01/01/2010 00:00' AND '06/30/2010 23:00'
AND DateHour NOT BETWEEN '05/01/2010 00:00' AND '05/31/2010 23:00'
AND Latitude = 41.995
AND Longitude = -87.9336
GROUP BY MONTH(DateHour);


Cela renverra la moyenne mensuelle de janvier à juin mais exclura mai. L'exclusion des enregistrements de mai 2010 est rendue possible par NOT BETWEEN. Voici le jeu de résultats dans la figure 4.

Illustration 4 . Ensemble de résultats d'une requête utilisant NOT BETWEEN.

SQL BETWEEN par rapport aux autres opérateurs

Conseil n° 9 :utilisez IN si vous avez besoin d'une liste et non d'une plage

L'opérateur IN détermine si une valeur correspond à une valeur dans une liste ou une sous-requête. Pendant ce temps, l'utilisation de NOT IN vérifie si une valeur ne correspond pas.

Les opérateurs BETWEEN et IN filtrent les données en fonction de plusieurs valeurs. Mais la différence réside dans l'ensemble de valeurs correspondant. BETWEEN utilise une plage. Mais IN utilise des valeurs séparées par des virgules dans une liste ou des lignes dans une sous-requête.

Vérifiez l'exemple ci-dessous.

SELECT
 DateHour
,[Hourly_Heating_Degree_Hours]
FROM TemperatureData
WHERE DateHour BETWEEN '06/01/2010' AND '06/5/2010 23:00'
AND [Hourly_Heating_Degree_Hours] IN (5.2, 6, 7, 3.7)
AND Latitude = 41.995
AND Longitude = -87.9336;


Regardez la liste des valeurs utilisées par IN. Il n'est pas nécessaire que ce soit une liste de valeurs croissantes. La dernière valeur de la liste (3.7) est également la plus petite parmi les nombres.

Astuce n° 10 :Choisissez entre ENTRE ou>=avec <=

Lors de l'exécution, SQL Server convertit BETWEEN en>=avec les opérateurs <=. Comment le savons-nous ?

Regardez le code ci-dessous.


SELECT
 DateHour
,AVG(Hourly_Heating_Degree_Hours) AS AverageTemp
FROM TemperatureData
WHERE DateHour BETWEEN '01/01/2010 08:00' AND '01/01/2010 12:00'
GROUP BY DateHour;

SELECT
 DateHour
,AVG(Hourly_Heating_Degree_Hours) AS AverageTemp
FROM TemperatureData
WHERE DateHour >= '01/01/2010 08:00' 
AND DateHour <= '01/01/2010 12:00'
GROUP BY DateHour;


Les deux requêtes auront le même jeu de résultats que celui de la figure 5.

Illustration 5 . Résultat défini en utilisant BETWEEN ou>=avec <=.

Ils ont également le même plan d'exécution, comme le montre la figure 6.

Illustration 6 . Plan d'exécution de 2 requêtes comparant l'utilisation des opérateurs BETWEEN, et>=et <=.

Mais voici le problème.

Remarquez le premier Index Rechercher opérateur dans la figure 6. Ensuite, consultez la section Rechercher des prédicats . Voyez-vous le mot-clé BETWEEN ? Il n'y en a pas, non ? Parce qu'il est converti en>=avec les opérateurs <=. Ce sont les opérateurs présents dans les Seek Predicates .

Mais il y a plus.

Si vous passez votre souris sur le deuxième Index Seek opérateur, vous verrez les mêmes propriétés que le premier Index Seek .

Donc, il semble que l'opérateur BETWEEN soit un raccourci vers>=avec les opérateurs <= . Vous taperez plus si vous utilisez ce dernier. Vous verrez la même conversion se produire lorsque BETWEEN est utilisé dans des nombres et des chaînes.

En fin de compte, c'est à vous de décider si vous utilisez BETWEEN ou les opérateurs>=et <=. Le temps de conversion nécessaire pour convertir BETWEEN est négligeable. Mais si vous ne voulez toujours pas ce temps supplémentaire négligeable, utilisez les opérateurs>=et <=.

Conclusion

SQL BETWEEN est bon pour récupérer des données incluant la plage. Et ce n'est pas si difficile à utiliser. Même les valeurs DATETIME sont gérables avec BETWEEN. Assurez-vous simplement de couvrir correctement la partie horaire. Cela équivaut également à utiliser>=avec <=. C'est à vous de décider lequel vous préférez utiliser.

Vous pouvez ajouter cette page à vos favoris pour obtenir des conseils SQL BETWEEN pour les dates, les nombres et les chaînes lorsque vous en avez besoin.

Si vous avez des astuces en utilisant BETWEEN que nous n'avons pas couvertes, vous pouvez les partager avec nous dans la section Commentaires. Et si vous aimez cet article, partagez-le en appuyant sur les boutons des réseaux sociaux.

Bon codage à tous !