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>
3 Réponses :
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.
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 ).
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 a>
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.