2017-10-18 8 views
0

J'ai hérité du code d'application C# qui a un constructeur de requête SQL fluide qui est utilisé dans notre base de code. Certaines des requêtes les plus courantes appliquent des filtres tels que "Date ou après aujourd'hui". Ces filtres sont stockés dans une table SQL en tant que métadonnées pour le générateur de requête. Lors de l'examen des problèmes de performances et de blocage, j'ai constaté que ces composants de requête ne sont pas sargables.Version Sargable de la requête SQL DateDiff()

Une requête typique construite par ce constructeur ressemble:

DECLARE @systemDate DATETIME 
SET @systemDate = [dbo].GetSystemDate() 

SELECT [table1].* FROM [dbo].[XXX] AS [table1] 
WHERE ... AND DateDiff(d, @systemDate, [table1].PaymentDate) <= 0 
AND ... 

La PaymentDate colonne est stockée en tant que datetime, avec un composant de temps. GetSystemDate() renvoie un datetime à minuit - ie 2017-10-18 00: 00: 00.000

Le problème est que même si j'ai PaymentDate dans un index de couverture SQL Server ne peut pas faire une recherche dessus car il est dans la fonction DateDiff(). Cependant, la conception du générateur de requêtes me permet de le remplacer facilement par une expression sargable plus efficace qui serait appliquée à toutes les requêtes SQL construites. Quelle serait une requête sargable équivalente pour ce qui suit étant donné que les composants temps sont également en jeu sur la colonne interrogée et que la requête résultante devrait renvoyer des résultats identiques aux appels DateDiff() existants? J'ai vu d'autres solutions autour de cette utilisation DateAdd() et les comparaisons, mais je me méfie de ceux qui se comportent différemment étant donné qu'il y a une composante de temps dans nos données.

OperatorDisplayName OperatorExpression ValueExpression ColumnExpression 
Today      =     0   DateDiff(d, @systemDate, {0}) 
This Week     =     0   DateDiff(ww, @systemDate, {0}) 
Last Week     =     -1   DateDiff(ww, @systemDate, {0}) 
This Month     =     0   DateDiff(m, @systemDate, {0}) 
Last Month     =     -1   DateDiff(m, @systemDate, {0}) 
On or Before Today   <=     0   DateDiff(d, @systemDate, {0}) 
On or After Today   >=     0   DateDiff(d, @systemDate, {0}) 
Before Today     <     0   DateDiff(d, @systemDate, {0}) 
After Today     >     0   DateDiff(d, @systemDate, {0}) 

Répondre

0

Depuis @systemDate n'a pas une composante de temps, vous pouvez construire> = < comparaisons:

OperatorDisplayName OperatorExpression ValueExpression ColumnExpression 
Today      =     0   {0} >= @systemDate AND {0} < DATEADD(d, 1, @systemDate) 

Vous n'utilisez pas vraiment l'opérateur ou la valeur de cette façon, car il est construit dans la expression de colonne. Les opérateurs semaine et mois seront plus compliqués car vos expressions devront inclure du code pour calculer le premier jour de la semaine/mois basé sur @systemDate, mais il existe déjà des exemples sur le web.