1
votes

Division d'une valeur de date dans T-SQL

Je travaille sur la migration d'un programme Access vers SQL Server. Voici mon code SQL extrait directement de l'accès.

Msg 257, Level 16, State 3, Line 1
Implicit conversion from data type datetime to int is not allowed. Use the 
CONVERT function to run this query.

Comme vous pouvez le voir, j'essaie de faire une division sur une valeur datetime.

C'est l'erreur message que je reçois:

(([Promise Date])-([Date Recieved]))/100

Les deux champs sont de type Datetime. Des idées ce qui me manque?


11 commentaires

Le message d'erreur est clair: Convertissez les valeurs de date en Double / Float, puis effectuez l'arithmétique.


Ce qui vous manque, c'est qu'il s'agit d'un non-sens syntaxique et que vous avez plus de travail à faire - et peut-être un apprentissage supplémentaire à faire avant cela. Vous devrez déterminer quel devrait être le résultat de ce calcul, puis le traduire en tsql. Je peux deviner que vous devriez utiliser datéiff pour obtenir le nombre de jours (?) Entre les dates et ensuite diviser, mais je n'ai aucune idée de ce que cela fait vraiment.


Appliquer l'arithmétique directement aux dates, en vérité, n'a guère de sens. Les dates ne sont pas des nombres, ce sont (sans surprise) des dates. Si je devais vous demander ce qu'était aujourd'hui (20190121) / 7, pourriez-vous répondre? Qu'en est-il de (la date) 20170804 * 2? Sans savoir ce que vous essayez vraiment d'accomplir ici, la réponse est difficile. Je soupçonne que les autres ont raison, que vous voulez la différence en jours / 100, et que vous devez donc utiliser DATEDIFF , cependant, nous devons également connaître quelques exemples de données et les résultats attendus.


Si vous avez également des valeurs de temps, c'est vraiment important, comme quelque chose comme DATEDIFF (DAY, '2019-01-20T00: 00: 00', '2019-01-21T23: 59: 59') est égal à 1, bien qu'il y ait essentiellement 2 jours d'intervalle, où comme DATEDIFF (DAY, '2019-01-21T23: 59: 59', '2019-01-22T00: 00: 01' ) est 1 , malgré qu'il n'y ait que 2 secondes entre les deux dates et heures.


@larnu - les dates d'accès sont des doubles IEEE, zéro étant 1899-12-31 je crois. Dans la réponse acceptée, je trouve que même SELECT DATEDIFF (jour, '2019-01-01', '2019-04-09') / 100; renvoie zéro, car DATEDIIF renvoie un entier et la division entière prend le dessus


Notez que DateDiff renvoie le nombre de frontières franchies, par exemple le nombre de jours du 2000-01-01 00:15:00 au 2000-01-01 23:45:00 est 0 , mais de 2000-01-01 23:59:30 à 2000-01-02 00:00:42 est 1 . Afin d'obtenir des résultats cohérents avec le code d'accès, vous devrez peut-être utiliser une partie de date plus petite, par exemple seconde plutôt que jour , avec un ajustement correspondant dans l'arithmétique, par ex. en divisant par 86400 . Notez que le type de retour est int ce qui limite la plage.


@Cato mon point ne change pas. 2019-01-21 / 2 n'a aucun sens. Les dates ne sont pas des nombres (et sachez que lorsque les gens les traitent comme des nombres, ils ont des problèmes).


@larnu date1 - date2 pourrait signifier quelque chose, en .net, c'est une période, mais le concept semble manquer dans SQL


@Cato en fait, il a été supprimé (n'était pas inclus) avec datetime2 et les autres nouveaux types de données; datetime le prend toujours en charge (mais encore une fois, cela ne veut pas dire que cela a du sens).


Je suis d'accord avec @Lamu sur le contexte. La façon dont je vois ce scénario, la demande est d'obtenir une différence entre les dates, puis de diviser par 100. Donc ... s'il y a une différence de 2 jours, les résultats sont 0,02? Que signifie 0,02? Je ne vois pas comment cela se traduit par quelque chose de significatif. Cela étant dit, l'accès MS permet la soustraction de deux dates comme OP présenté. Diviser par 100 est la curiosité. À cette fin, je ne pense pas que la réponse choisie produise le même résultat que MS Access car elle fonctionne comme Int. J'obtiens un zéro lorsque je l'essaye au lieu d'une valeur décimale.


@ level3looper - cela pourrait faire partie d'un calcul plus large, par exemple de simples paiements d'intérêts quotidiens - s'il s'agissait d'un intérêt de 1% par jour par exemple


3 Réponses :


4
votes

Je pense que si j'ai raison, vous cherchez quelque chose comme ceci

SELECT DATEDIFF(day, [Promise Date], [Date Recieved])/100;

Si vous avez raison, vous pouvez obtenir plus de détails ici

p>


4 commentaires

En fait, je pense que vous devriez inverser les deux paramètres de date


@GeorgeMenoutis Cela pourrait être


Cela a fait le travail. J'envisageais de le faire au départ, mais je pensais que j'aurais le même problème en divisant par 100. Merci @SurajKumar


Puisque DateDiff compte les franchissements de limites (comme indiqué dans mon commentaire sur la question), la valeur est probablement quelque peu différente de celle renvoyée dans Access. Le code TSQL retournera ici le résultat de la division entière, contrairement à l'expression Access, sauf si la constante est modifiée ( 100.0 ) ou un cast (ou convert ) est ajouté.



3
votes

étant donné que les dates d'accès sont effectivement stockées en DOUBLE, je recommanderais la conversion au type flottant SQL pour gérer toutes les parties de jours

declare @x as datetime = '19960420 15:05:48';
declare @y as datetime = '19960423 18:09:23';

select (CAST(@y as float) -  CAST(@x as float)) / 100

select (CAST(@y as int) -  CAST(@x as int)) / 100

select datediff(day,@x,@y) / 100

select cast(datediff(day,@x,@y) as float) / 100

consultez l'exemple suivant, les différentes idées ici donnent tout à fait réponses différentes

 (cast([Promise Date] as float) - cast([Date Recieved] as float))/100

L'accès doit traiter les dates comme des flottants, la partie fractionnaire représentant le temps et la partie entière représentant les jours


1 commentaires

C'est le plus précis.



1
votes
-0.0375

1 commentaires

cela fonctionne si son accès datetime contient toujours des dates entières, mais pas si elles contiennent des composants d'heure, par exemple 2001-01-01 19:00:00 jusqu'au 2001-01-05 13:00:00 par exemple