1
votes

Cette clause where retournera-t-elle toujours false?

J'essaie d'optimiser une requête assez complexe et je pense avoir trouvé un bogue dans le processus. J'attends des éclaircissements sur ce que, exactement, la vérification suivante est censée vérifier, mais en attendant, je suis presque sûr que cette clause where dans l'une des sous-requêtes retournera toujours false . Ai-je raison?

where dateField between GetDate() and DateAdd(m, -6,dateField)

Ai-je tort dans mon interprétation du fait que cela devrait être après (ou égal à) maintenant ET avant 6 mois avant lui-même, ce qui ne serait jamais vrai? p>


0 commentaires

3 Réponses :


4
votes

Oui, BETWEEN n'est pas symétrique. La valeur testée doit être supérieure (ou égale) à la première valeur mentionnée et inférieure (ou égale) à la deuxième valeur mentionnée.

Si la valeur testée est supérieure à la deuxième valeur mentionnée, elle ne peut jamais correspondre.


0 commentaires

0
votes

Cette clause where toujours renvoie-t-elle false?

D'un point de vue technique, cela pourrait également générer INCONNU lorsque la colonne est nullable

NULL et INCONNU (Transact-SQL)

Lorsque des valeurs nulles sont présentes dans les données, les opérateurs logiques et de comparaison peuvent potentiellement renvoyer un troisième résultat INCONNU au lieu de simplement TRUE ou FALSE


Pour cet exemple particulier, il ne peut pas être TRUE (il peut être FALSE / INCONNU ).


2 commentaires

Pédantique - surtout quand PERSONNE n'a rien dit sur la nullité.


@SMor Keyword: "toujours" :). Ignorer Nullability crée de la confusion, c'est pourquoi il convient de mentionner par exemple ici



1
votes

Vous pouvez le tester vous-même avec des variantes de ce code:

declare @basedate datetime = dateadd(month, -7, current_timestamp);

with digits as (
   SELECT * 
   FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9) ) n(digit)
), 
numbers as (
select d1.digit + (d2.digit*10) + (d3.digit*100) number
from digits d1
cross join digits d2
cross join digits d3
),
dates as (
    select dateadd(day, number, @basedate) as dateField 
    from numbers
)
select dateField, case when dateField between GetDate() and DateAdd(m, -6,dateField) then 'True' else 'False' end as Result
from dates
--OPTIONAL, if you just want to see the "True" results (hint: there are none, which is why I left it off... so you can see the query does run)
-- WHERE dateField between GetDate() and DateAdd(m, -6,dateField)
order by dateField

Cela vérifiera une valeur pour chaque date d'avant 6 mois avant la date actuelle jusqu'à plus de 6 mois après la date actuelle date.

Effectivement, il ne renvoie jamais Vrai.


0 commentaires