2017-09-26 1 views
0

Si un utilisateur sélectionne une plage telle que:Vérifiez si la date tombe dans la plage Mois et Année

  • Début: Novembre 2016
  • Fin: Septembre 2017,

Je veux inclure tous résultats compris entre 2016-11-01 et 2017-09-30.

J'ai essayé de concaténer ensemble l'année, le mois et le jour, mais le problème vient du fait que tous les mois n'ont pas le même jour. Bien que je sache que tous les mois commencent le jour 01, le jour d'un mois peut être 28, 29, 30 ou 31.

Y a-t-il un moyen de le faire sans construire la date? SqlServer 2008 n'a pas la fonction EOMONTH, et je me sens comme quelque chose de plus complexe que ce n'est pas la bonne solution. Je voudrais éviter cela:

WHERE 
    DateCol >= '2016' + '-' + '11' + '-01' AND 
    DateCol <= '2017' + '-' + '09' + '-30' 
+3

'où DATE_1> = '20161101' et DATE_1 <= « 20170930'' - Les seuls formats vraiment sûrs pour littéraux date/heure dans SQL Server, au moins pour 'datetime' et' smalldatetime', sont: 'YYYYMMDD' et' YYYY-MM-DDThh: mm: ss [.nnn] '- [Mauvaises habitudes de coup de pied: mauvaise manipulation des requêtes de date/distance - Aaron Bertrand] (http : //sqlblog.com/blogs/aaron_bertrand/archive/2009/10/16/bad-habits-to-kick-mishandling-date-range-queries.aspx) – SqlZim

+2

https://blogs.msdn.microsoft.com/ samlester/2013/09/23/eomonth-equivalent-en-sql-server-2008-r2-et-dessous/ – ttugates

+0

@SqlZim, je ne parle pas vraiment de format. L'année et le mois sont sélectionnés par l'utilisateur. Donc, s'ils ont choisi septembre 2017, comment avez-vous su ajouter l'appendice 30 à la date «20170930»? – user7733611

Répondre

1

Il me semble vraiment que la réponse la plus facile et la meilleure est de passer du premier mois du mois au premier du mois suivant le mois de fin, et de ne pas inclure la deuxième comparaison.

En d'autres termes, au lieu de cela:

WHERE 
    DateCol >= '2016' + '-' + '11' + '-01' AND 
    DateCol <= '2017' + '-' + '09' + '-30' 

simplement ceci:

WHERE 
    DateCol >= '2016' + '-' + '11' + '-01' AND 
    DateCol < '2017' + '-' + '10' + '-01' 
+0

Cela semble être une bonne idée. Je ne suis pas sûr de ce que je ferais dans le cas de Décembre cependant. Cela signifie que je devrais augmenter l'année de façon conditionnelle (et changer le mois de 12 à 1). – user7733611

+0

Facile à faire avec la fonction 'DATEADD (mois, ...)'. –

+0

@Sami et pourquoi pas? –

0

Pour 2008, vous pouvez simplement convertir la chaîne

Exemple

Select Date1=convert(date,'November 2016') 
     ,Date2=dateadd(DAY,-1,dateadd(MONTH,1,convert(date,'September 2017'))) 

Retours

Date1  Date2 
2016-11-01 2017-09-30 

Ainsi WHERE serait somt Hing comme celui-ci

... 
Where DateCol between convert(date,'November 2016') 
        and dateadd(DAY,-1,dateadd(MONTH,1,convert(date,'September 2017'))) 
+0

Je pense que la question de l'OP était la fin des mois, 30 ou 31 ou 28. – Sami

0

Vous pouvez utiliser l'instruction select suivante pour obtenir la dernière date d'un mois (et une année) en passant un champ ou la date à elle:

DECLARE @dtDate DATE 
SET @dtDate = '09/25/2016' 
SELECT CAST(DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@dtDate)+1,0)) AS DATE) AS LastDay_AnyMonth 

S'il vous plaît fournir quelques exemples de données et résultat souhaité et je mettrai à jour ma réponse plus loin.

+0

Je me suis penché là-dessus en cherchant des alternatives à EOMONTH. Je voulais finalement éviter d'avoir même à comprendre le dernier jour du mois. – user7733611

+0

Quelle est la raison pour laquelle vous essayez d'éviter de comprendre le dernier jour du mois? – NonProgrammer

+0

Je pourrais comprendre.Mais logiquement, c'est hors de propos, n'est-ce pas? Au lieu de se concentrer sur la comparaison des mois et des années. – user7733611

0

vous allez ici:

DECLARE @YourTable TABLE (YourData DATE); 


INSERT INTO @YourTable VALUES 
('2016-11-01'), 
('2016-09-05'), 
('2017-03-03'), 
('2017-11-11'), 
('2017-12-14'), 
('2017-09-30'); 

WITH CTE AS (
    SELECT YourData 
    FROM @YourTable 
    WHERE YEAR(YourData) =2016 AND MONTH (YourData) >= 11 
    ) 
    SELECT YourData 
    FROM @YourTable 
    WHERE YEAR(YourData) =2017 AND MONTH (YourData) <= 9 
    UNION ALL 
    SELECT YourData 
    FROM CTE; 

Il n'y a pas besoin de connaître la fin du mois (28 ou 30 ou 31).

+0

Cela ne fonctionnerait pas. Vous excluez les données de 2016 – NonProgrammer

+0

Votre réponse exclurait toujours des résultats tels que 2017-01-01 – user7733611

+0

@ user7733611 Voir les mises à jour. – Sami

1

Il y a une façon plus rapide de le faire:

DECLARE @minDate DATE 
DECLARE @maxDate DATE 
SET @minDate = XXXXX 
SET @maxDate = YYYYY 

-- Get the first day of the month minDate. 
SET @minDate = CONVERT(datetime,CONVERT(varchar(6),@minDate,112)+'01',112) 
-- Get the last day of the month minDate. 
SET @maxDate = CONVERT(datetime,CONVERT(varchar(6),@maxDate,112)+'01',112) 
SET @maxDate = DATEADD(day, -1, DATEADD(month, 1, @maxDate)) 


SELECT * FROM myTABLE WHERE DateCol >= @minDate AND DateCol <= @maxDate 

Ou:

SELECT * FROM myTABLE 
WHERE DateCol >= CONVERT(datetime,CONVERT(varchar(6),XXXXX,112)+'01',112) 
    AND DateCol <= DATEADD(day, -1, DATEADD(month, 1, CONVERT(datetime,CONVERT(varchar(6),YYYYY,112)+'01',112))) 

Utilisez la syntaxe comme CONVERT (datetime, '20170930', 112) ou CONVERT (datetime, '09 -30-2017 ', 110) pour XXXXX et YYYYY plutôt que' 2017-09-30 'qui utilisent SQL Server implicitement conversion de char à datetime (compter sur la configuration du serveur: peut être dangereux !!!)).

Cette syntaxe est plus rapide car @minDate et @maxDate n'ont besoin d'aucune évaluation. Alors que les indices peuvent être utilisés directement ...

Sinon une fonction scalaire qui simulent le comportement EOMONTH() pourrait être utile ...

+0

Ça vous dérange d'expliquer cette ligne: CONVERT (datetime, CONVERT (varchar (6), XXXXX, 112) + '01', 112) À quoi servent les 112? – user7733611

+1

112 signifie CONVERT que le deuxième paramètre doit être un format de texte ISO d'une date: AAAAMMJJ. 110 est pour le format US: MM-JJ-AAAA. Voir https://www.w3schools.com/sql/func_sqlserver_convert.asp pour plus de détails ... – clementakis

+1

Le format de conversion implicite de date en char peut être vérifié par 'SELECT CAST (getdate() AS VACHAR (20))'. Le résultat vous donne le format de texte attendu par votre SQL Server. Cela peut varier d'une machine à l'autre, même dans la même entreprise ... – clementakis

0

Construction utile pour effectuer des opérations basées sur la date est d'utiliser un tableau de dimensions de date. Vous créez une table de recherche contenant de nombreuses informations sur les dates sur une longue période. Vous pouvez ensuite interroger la table en fonction des informations que vous possédez. La table est suffisamment petite pour ne pas imposer de problèmes de performance significatifs.

Dans votre cas particulier, vous avez le mois et l'année. Vous devez le brancher dans la table de dimension de la date pour obtenir le premier mois du mois de début et le dernier mois du mois de fin. Vous avez maintenant une plage de temps pour effectuer une recherche sans aucune logique complexe ou calculs à la volée.

Aaron Bertrand explique en profondeur ici: https://www.mssqltips.com/sqlservertip/4054/creating-a-date-dimension-or-calendar-table-in-sql-server/