|
Publicité ' | ||||||||||||||||||||||||
|
|
#1 | ||||
|
Membre éprouvé
![]() Nero PaulAutodidact,Concepteur et développeur informatique Inscription : octobre 2010 Messages : 387 ![]() |
Bonjour,
depuis des années j'utilise cette requête dans un DTS pour me charger des données dans un fichier chaque début du mois.Il charge ainsi les données du mois précédent: Code sql :
j'ai ainsi opté pour cette procédure T-SQL: Code sql :
Pensez vous que cela est optimisé? des idées?
__________________
Cordialement, J'ose espérer que m'a contribution vous a été d'une grande aide. Pensez tout de Même à dire MERCI et marquer RESOLU en cas de satisfaction. Paul |
||||
|
|
00
|
|
|
#2 | ||
|
Membre Expert
![]() Analyste / Programmeur / DBA Inscription : juillet 2006 Messages : 1 924 ![]() |
Pourquoi ne pas faire ceci ?
Code sql :
Il faudra juste p-e adapter les bornes de l'opérateur between pour correspondre exactement à votre besoin.
__________________
Kropernic (anciennement Griftou). |
||
|
|
00
|
|
|
#3 |
|
Membre éprouvé
![]() Nero PaulAutodidact,Concepteur et développeur informatique Inscription : octobre 2010 Messages : 387 ![]() |
Merci de ta participation,
mais je pense pas que datediff résoudra le problème de janvier!! en effet, si je suis le 2 janvier 2013 et que je veuille récupérer les données du mois d'avant, j'ai un getdate() qui me retournera 2013 et si je fais month -1 j'ai "0" donc la requête ne retournera rien du tout. cordialement
__________________
Cordialement, J'ose espérer que m'a contribution vous a été d'une grande aide. Pensez tout de Même à dire MERCI et marquer RESOLU en cas de satisfaction. Paul |
|
|
00
|
|
|
#4 |
|
Membre Expert
![]() Analyste / Programmeur / DBA Inscription : juillet 2006 Messages : 1 924 ![]() |
Et bien justement non.
C'est là tout l'intérêt de travailler sur les types de données corrects. Tu veux faire un traitement sur une date (obtenir la date un mois avant dans ce cas). Il faut donc travailler avec des dates et les fonctions appropriées. La fonction DATEDIFF renverra une date (valide!) qui correspondra à ce qui lui a été passé en paramètre. En utilisant la fonction MONTH(qui retourne un entier!), tu sors du "domaine" des dates et obtient donc des résultats farfelus en appliquant des traitements à priori triviaux dessus. Tout le monde sait bien que le mois avant janvier est décembre (même les SGDBR) mais si tu lui dis de prendre l'entier avant 1, il est normal qu'il te réponde que c'est 0. J'en ferais de même.
__________________
Kropernic (anciennement Griftou). |
|
|
00
|
|
|
#5 | |||
|
Membre éprouvé
![]() Nero PaulAutodidact,Concepteur et développeur informatique Inscription : octobre 2010 Messages : 387 ![]() |
Citation:
bon devenons sérieux. si je te prends au mot, cela donnerait ceci dans ma requête: Code sql :
mais il me semble que si j'exécute ça le 5 du mois par exemple, il me prendra les données entre le 1er et le 5? cordialement
__________________
Cordialement, J'ose espérer que m'a contribution vous a été d'une grande aide. Pensez tout de Même à dire MERCI et marquer RESOLU en cas de satisfaction. Paul |
|||
|
|
00
|
|
|
#6 | |||
|
Membre éprouvé
![]() Nero PaulAutodidact,Concepteur et développeur informatique Inscription : octobre 2010 Messages : 387 ![]() |
Citation:
bon devenons sérieux. si je te prends au mot, cela donnerait ceci dans ma requête: Code sql :
mais il me semble que si j'exécute ça le 5 du mois par exemple, il me prendra les données entre le 1er et le 5? cordialement
__________________
Cordialement, J'ose espérer que m'a contribution vous a été d'une grande aide. Pensez tout de Même à dire MERCI et marquer RESOLU en cas de satisfaction. Paul |
|||
|
|
00
|
|
|
#7 | ||||
|
Membre Expert
![]() Analyste / Programmeur / DBA Inscription : juillet 2006 Messages : 1 924 ![]() |
Content de t'avoir fait rire. Il y a 2 ans (avant que je m'investisse personnellement dans l'apprentissage du monde des DB), je faisais comme toi pour ce genre de chose en utilisant la fonction Month et en me faisant ch*** pour gérer les débuts et fin d'années.
Puis j'ai compris qu'il fallait travailler avec les types de données et depuis, ça va beaucoup mieux. Bref, revenons à ton problème. Tout d'abord, je tiens à m'excuser car j'ai utilisé la mauvaise fonction... Il s'agit bien sûr de DATEADD et non pas DATEDIFF. DATEDIFF retourne un entier et non pas une date (ce qui fait qu'on retombe dans le genre de cas où ça ne va pas). Il n'empêche que le raisonnement reste le même. La clause WHERE telle qu'écrite dans ta requête demande que date_encais soit égale à date_encais avec un mois de moins (pour la première condition). Si je caricature un peu, cela revient à écrire On se rend vite compte qu'il y a un souci (mais cela vient p-e de la confusion que j'ai introduite par l'utilisation de la mauvaise fonction). Si j'ai bien compris, tu veux donc les lignes dont la valeur de la colonnes date_encais se trouve dans le mois précédent le mois en cours. J'écrirais donc une clause WHERE ressemblant (je reste prudent) à ceci : Code :
Code :
WHERE date_encais BETWEEN '20121208' AND '20130108' Je ferais quelque chose du genre : Code :
__________________
Kropernic (anciennement Griftou). |
||||
|
|
00
|
|
|
#8 | ||
|
Membre Expert
![]() Analyste / Programmeur / DBA Inscription : juillet 2006 Messages : 1 924 ![]() |
Maintenant qu'on a donc notre date de référence, la clause WHERE devient (presque) évidente :
Code :
__________________
Kropernic (anciennement Griftou). |
||
|
|
00
|
|
|
#9 | ||
|
Expert Confirmé
![]() Inscription : janvier 2010 Messages : 1 689 ![]() |
Bonjour,
Attention, il n'y a pas que le probleme du jour, mais également des heures, minutes,... plus simplement, pour "arrondir" une date vous pouvez combiner un DATEADD et un DATEDIFF par rapport à une date arbitraire (0 dans l'exemple ci dessous) Votre clause WHERE devient donc Code :
|
||
|
|
20
|
|
|
#10 | |||
|
Membre Expert
![]() Analyste / Programmeur / DBA Inscription : juillet 2006 Messages : 1 924 ![]() |
Citation:
Sinon, histoire d'être complet, voici comment j'aurais fait si la colonne était de type DATETIME (Je ne dénigre nullement la manière de faire montrée par aieeeuuuu). Et donc, avec une colonne de type DATETIME, j'aurais juste exclue la partie time du problème. Pour la date de référence (j'ai changé le nom de variable par faire plus court) : Code :
(la note signalée par aieeeuuuu en fin de message restant valable).
__________________
Kropernic (anciennement Griftou). |
|||
|
|
00
|
|
|
#11 |
|
Membre Expert
![]() Analyste / Programmeur / DBA Inscription : juillet 2006 Messages : 1 924 ![]() |
Je me rends compte d'une coquille dans la solution que j'ai proposée.
Telle quelle, le critère de la requête si elle était exécutée aujourd'hui serait du 01/12/2012 au 01/01/2013. De ce fait, cela peut être problématique. Si la colonne est de type DATE, il faut bien sûr retirer un jour à la borne supérieur. Si la colonne est de type DATETIME, là ça marche car, implicitement, sql server ajoute 00:00:00.000 comme composante temporelle.
__________________
Kropernic (anciennement Griftou). |
|
|
00
|
|
|
#12 |
|
Membre éprouvé
![]() Nero PaulAutodidact,Concepteur et développeur informatique Inscription : octobre 2010 Messages : 387 ![]() |
Bonjour,
et désolé pour hier, je suis rentré trop tôt. Quand je lis le fil de la discussion, je me rends compte qu'on a toujours les problèmes du premier jour du mois suivant.Or, moi si j'exécute mon DTS le 3 janvier 2013, je soushaite avoir les données de 1/12/2012 au 31/12/2012 à minuit. C'est pour éviter les contraintes de datetime et smalldatetime que j'ai préféré gerer des entiers, d'où mon premier script T-sql. cordialement
__________________
Cordialement, J'ose espérer que m'a contribution vous a été d'une grande aide. Pensez tout de Même à dire MERCI et marquer RESOLU en cas de satisfaction. Paul |
|
|
00
|
|
|
#13 |
|
Membre Expert
![]() Analyste / Programmeur / DBA Inscription : juillet 2006 Messages : 1 924 ![]() |
Quel est le type de donnée de la colonne date_encais (colonne sur laquelle s'effectue le filtre) ?
Il n'y a pas de problème, il faut juste bien comprendre comment fonctionne sql server. Si la colonne est de type DATETIME (ce qui était d'office le cas avec sql server 2005 et antérieures), quand on écrit une condition du genre Code :
date_encais BETWEEN '20121201' AND '20121231' Code :
date_encais BETWEEN '20121201 00:00:00.000' AND '20121231 00:00:00.000' De ce fait, toujours en partant de la formule de calcule d'une date de référence que j'ai donnée précédemment, le filtre de la clause where est Code :
date_encais BETWEEN dateadd(month,-1,@ladate) AND @ladate En remplaçant les fonctions et variables par leur valeur, on a donc le filtre suivant qui correspond à ce qui est souhaiter : Code :
date_encais BETWEEN '20121201 00:00:00.000' AND '20130101 00:00:00.000' Si la colonne est de type date, sql server ne "traduit" rien du tout vu qu'il n'a pas à ajouter de composante temporelle pour coller au type de donnée. Du coup, toujours avec la même valeur pour la variable @ladate, une condition telle qu'écrite ci-dessus intégrera les données du premier janvier qui ne devraient pas l'être. Il faut donc y retirer un jour.
__________________
Kropernic (anciennement Griftou). |
|
|
00
|
|
|
#14 | ||
|
Expert Confirmé
![]() Inscription : janvier 2010 Messages : 1 689 ![]() |
Je suppose que vous vouliez dire du 1/12/2012 au 31/12/2012 à 23:59:59.999...
comme le dit Kropernic, cela dépend du type de votre colonne, mais dans la requete que je vous ai proposée, seules les données du 1/01/2013 à 0:00:00.000 seront incluses. Pour éviter ce cas, vous pouvez modifier dans la clause WHERE que je vous ai proposée le BETWEEN par un >= et un < : Code :
|
||
|
|
10
|
|
|
#15 | |||
|
Membre Expert
![]() Analyste / Programmeur / DBA Inscription : juillet 2006 Messages : 1 924 ![]() |
Citation:
Je me demande ce qui est conseillé en pratique par les "experts" du monde sql server. Sinon, j'imagine qu'il est toujours possible de retirer une milliseconde à la borne supérieure de l'intervalle voulu XD. Reste à savoir ce qui est le plus performant entre between et <=, > (mais p-e que l'optimiseur de requête traduit cela en between )
__________________
Kropernic (anciennement Griftou). |
|||
|
|
00
|
|
|
#16 | |
![]() ![]() ![]() Frédéric BROUARDExpert SGBDR & SQL Inscription : mai 2002 Messages : 12 074 ![]() |
Citation:
Code :
SELECT DATEADD(ms, -1, CAST('20121231 00:00:00.000' AS DATETIME))
__________________
Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL Site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/ Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp. Blog SQL, SQL Server, modélisation données : http://blog.developpez.com/sqlpro http://www.sqlspot.com : modélisation, conseils, audit, optimisation, formation * * * * * Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence * * * * * |
|
|
10
|
|
|
#17 |
|
Membre éclairé
![]() Développeur informatique Inscription : octobre 2006 Messages : 209 ![]() |
tu peux aussi essayer quelque chose comme :
Code :
datediff(mm,date_encais,dateadd(mm,-1,getdate())=0 |
|
|
01
|
|
|
#18 | |
|
Expert Confirmé
![]() Inscription : janvier 2010 Messages : 1 689 ![]() |
Citation:
|
|
|
|
10
|
|
|
#19 |
|
Membre éclairé
![]() Développeur informatique Inscription : octobre 2006 Messages : 209 ![]() |
AMHA ca resoud le probleme de l'heure et ce n'est pas plus penalisant que les
Code :
year(date_encais) et month(date_encais) |
|
|
00
|
|
|
#20 |
|
Membre Expert
![]() Analyste / Programmeur / DBA Inscription : juillet 2006 Messages : 1 924 ![]() |
C'est justement ce qui est évité avec les méthodes proposées par aieeeuuuu et moi-même.
Lorsqu'une fonction est appliquée sur une colonne de la clause WHERE, cela rend impossible l'utilisation de l'index approprié (à condition qu'il existe évidemment). Ce n'est donc pas plus pénalisant que la méthode de la requête initiale certes. Mais cela n'en reste pas moins pas optimal pour les performances.
__________________
Kropernic (anciennement Griftou). |
|
|
00
|
Copyright © 2000-2013 - www.developpez.com