Pour get la dernière date du mois précédent jusqu'à la dernière seconde

Je veux get la dernière date du mois dernier ( 30 ou 31 ) et l'heure jusqu'à la dernière seconde, chaque fois que la requête est exécutée. Par exemple. 30/11/2015 23:59:59

J'ai donc une requête comme

 SELECT DATEADD(ss, (60*60*24)-1, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), -1)) 

Cela résout mon problème. Mais quelle est la différence entre la requête écrite ci-dessus et celle ci-dessous, quand je change la partie DATEDIFF et remplace 0 par 1 ?

 SELECT DATEADD(ss, (60*60*24)-1, DATEADD(MONTH, DATEDIFF(MONTH, 1, GETDATE()), -1)) 

Est-ce que ces deux requêtes donneront le même résultat à chaque exécution, ou que devrais-je considérer comme la solution permanente?

Ne faites pas cela; tenter d'get la "dernière seconde" du dernier jour du mois précédent

Je fais cette déclaration audacieuse sur l'hypothèse que vous essayez d'utiliser BETWEEN et vous êtes préoccupé par l'exactitude de quelque chose comme ceci:

 select sum(value) from Atable where [Adate] BETWEEN '20151201' AND '21051231 59:59:59' 

Mais la complexité d'arriver au dernier moment le dernier jour d'un mois est résolue si facilement en utilisant le premier jour du mois suivant à la place. Tout ce que vous devez également faire est de supprimer l'utilisation de BETWEEN. Comme ça:

 select sum(value) from Atable where [Adate] >= '20151201' and [Adate] < '21060101' 

MOINS QUE "le premier jour du mois"

Voilà comment vous résolvez votre énigme.

& au fait: La précision (précision) de smalldatetime, datetime et datetime2 diffèrent, raison de plus pour ne pas utiliser BETWEEN.

voir " Attention aux erreurs d'arrondi " sur http://sqlmag.com/t-sql/t-sql-best-practices-part-2


Plus précisément, faites ceci:

DateLogged <SELECT DATEADD (MOIS, DATEDIFF (MONTH, 0, GETDATE ()), 0)

Ce sera précis à 100% pour les colonnes date, smalldatetime, datetime et datetime2.


Voici une autre tentative pour expliquer pourquoi MOINS QUE [the_next_day_at_00: 00: 00 + 0000000] est précis et que 22:59:59 n'est PAS exact. Veuillez prendre note de l'exactitude des données de l'échantillon

SQL Fiddle

Configuration du schéma MS SQL Server 2014 :

Requête 1 :

 DECLARE @Tbl TABLE ( [ID] int identity(1,1) , [DT_a] datetime , [DT_b] datetime , [DT_c] datetime2 ) INSERT INTO @Tbl ([Dt_a], [Dt_b], [Dt_c]) VALUES ( '20151231 23:59:59' , '20151231 23:59:59.997' , '20151231 23:59:59.9999999' ) select 'where [DT_b] <= 20151231 23:59:59' as FilterSsortingng , max([Dt_a]) as [Dt_a] , max([Dt_b]) as [Dt_b] , max([Dt_c]) as [Dt_c] from @Tbl where [DT_b] <= '20151231 23:59:59' UNION ALL select 'where [DT_b] < 20160101' , max([Dt_a]) as [Dt_a] , max([Dt_b]) as [Dt_b] , max([Dt_c]) as [Dt_c] from @Tbl where [DT_b] < '20160101' 

Résultats :

 | FilterSsortingng | Dt_a | Dt_b | Dt_c | |-----------------------------------|----------------------------|----------------------------|-----------------------------| | where [DT_b] <= 20151231 23:59:59 | (null) | (null) | (null) | | where [DT_b] < 20160101 | December, 31 2015 23:59:59 | December, 31 2015 23:59:59 | 2015-12-31 23:59:59.9999999 | 

Précision des données

  • smalldatetime : une minute
  • datetime : arrondi à des incréments de .000, .003 ou .007 secondes
  • datetime2 : 100 nanosecondes

Pour éviter les erreurs d'arrondi par unité de time, NE PAS UTILISER <= 23:59:59

Au lieu de cela, utilisez less que [the_next_day]

ET, par conséquent, évitez d'utiliser entre les plages de dates.

Voir ce lien pour savoir comment DATEDIFF est utilisé ou devrait être utilisé dans SQL Server. Le deuxième argument, celui qui ne semble pas faire de différence dans votre cas, est censé être la date de début qui est soustraite de la date de fin (getdate ()) pour get la différence et ensuite convertie en mois. J'essaierais d'utiliser cette fonction de la manière habituelle et de fournir une bonne date de début.

Voici également une autre façon d'get le même résultat

 SELECT DATEADD(ss, -1, '01/' + CONVERT(VARCHAR, DATEPART(MONTH, getdate())) + '/' + CONVERT(VARCHAR, DATEPART(YEAR, getdate()))); 

C'est à cause de DATEDIFF( MONTH, 0, GETDATE()) Fonction

Si vous utilisez un entier comme deuxième argument, cela est interprété comme le nombre de jours 1900-01-01 depuis 1900-01-01 quel que soit l'Interval que vous utilisez dans la fonction datediff .

Par exemple:

  SELECT YEAR(0), MONTH(0), DAY(0); 
  year month day 1900 1 1 

Maintenant, si je incrémente 0 à 1 dans l'année, le mois, le jour

 SELECT YEAR(1), MONTH(1), DAY(1); 
  year month day 1900 1 2 

Maintenant, si j'augmente les valeurs à 365,

  SELECT YEAR(365), MONTH(365), DAY(365); 
  year month day 1901 1 1 

Vous pouvez voir que l'année a été incrémentée de 1.

Il y a plusieurs façons de find la dernière date du mois précédent. Voici celui que j'utilise.

 SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0))