IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

MS SQL Server Discussion :

Trouver quel mois précède quel mois pour table de calendrier relatif [2008R2]


Sujet :

MS SQL Server

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre du Club
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Mars 2014
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2014
    Messages : 6
    Par défaut Trouver quel mois précède quel mois pour table de calendrier relatif
    Bonjour,

    Dans le cadre de mon travail j'ai créé une table Calendrier qui décompose chaque date en année mois jours (et semaine aussi, voir ci dessous). Une ligne par jour de 2009 à 2020.

    Nom : calendrier basique.JPG
Affichages : 483
Taille : 32,8 Ko

    Jusque là, rien de méchant.


    J'ai rajouté les colonnes Mois-3, Mois-2, Mois-1, Mois-M, Mois+1, Mois+2, Mois+3 (même chose avec les années, les semaines et les jours), toutes de types BIT, remplies avec des zéro.

    Les choses de corsent quand je souhaite UPDATE lesdites colonnes, en mettant la valeur du champ à 1 si, effectivement, la date de la ligne satisfait la condition de la colonne. En effet, mon but est de comparer une date du calendrier à la valeur de GETDATE() :
    Si la date de la table Calendrier est 1er mai 2014, elle se trouve dans le même mois que celle de GETDATE() et la valeur de Mois-M est à 1, les 6 autres valeurs (relatives aux mois) sont donc à 0.
    Si la date de la table Calendrier est le 30 avril 2014, elle ne se trouve pas dans le même mois que celle de GETDATE() et la valeur de Mois-M est à 0 mais celle de Mois-1 est à 1, les 5 autres valeurs sont donc à 0.
    Si la date de la table Calendrier est 2 mai 2010, elle se trouve dans le même mois que celle de GETDATE() mais l'année est différente, la valeur de Mois-M devra être à 0, les 6 autres valeurs aussi.

    J'ai peur de ne pas être très clair, voici une petite maquette de ce que je souhaite obtenir :
    Nom : objectif.JPG
Affichages : 377
Taille : 32,4 Ko


    Je compte exécuter quotidiennement une procédure mettant à jour tous ces champs booléens.
    Exemple de ce que je fais pour la colonne Mois N+1 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    UPDATE [CALENDRIER]
    SET [Cd_Mois_N+1] = 1
    where [Cd_Mois]=month(getdate())+1 and [Cd_Annee]=year(getdate())
    Le problème (enfin) :

    Ce code marche parfaitement aujourd'hui car nous sommes en milieu d'année mais si la procédure s'exécute en février 2015, les dates de décembre 2014 n'auront pas leur case Mois N-2 cochée.

    Je pourrais tester avec des CASE toutes les possibilités mais étant donné que je devrai faire de même avec les jours et les semaines, la tâche s'annonce plutôt laborieuse donc je me dis que je manque surement d'astuce..

    Je m'en remets donc à votre expérience pour trouver une solution plus élégante !

    N'hésitez pas à me demander de compléter mon explication si besoin. Merci par avance.

  2. #2
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    Bonjour,

    Cette modélisation est assez étrange... Quel est le but de ces colonnes M-3, M-2,...

    Vous pourriez plutôt utiliser DATEDIFF(MONTH,...) pour calculer ces valeurs, cela vous affranchirai de votre problème de changement d'année.

    De plus, afin de vous éviter la mise à jour quotidienne, vous pourriez simplement créer une vue qui serait de fait toujours à jour :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    CREATE TABLE LaTable(
    	d DATETIME2(0)
    );
     
    INSERT INTO LaTable VALUES
    ('2011-02-01')
    ,('2011-05-02')
    ,('2014-02-03')
    ,('2014-03-30')
    ,('2014-05-05')
    ,('2014-06-06')
    ,('2014-07-07')
    ,('2014-08-08')
    GO
     
    CREATE VIEW LaVue
    AS
    SELECT 
    	d
    	,CASE WHEN DATEDIFF(MONTH,GETDATE(),d ) = -3 THEN 1 ELSE 0 END AS [M-3]
    	,CASE WHEN DATEDIFF(MONTH,GETDATE(),d ) = -2 THEN 1 ELSE 0 END AS [M-2]	
    	,CASE WHEN DATEDIFF(MONTH,GETDATE(),d ) = -1 THEN 1 ELSE 0 END AS [M-1]
    	,CASE WHEN DATEDIFF(MONTH,GETDATE(),d ) = 0 THEN 1 ELSE 0 END AS [M]	
    	,CASE WHEN DATEDIFF(MONTH,GETDATE(),d ) = 1 THEN 1 ELSE 0 END AS [M+1]
    	,CASE WHEN DATEDIFF(MONTH,GETDATE(),d ) = 2 THEN 1 ELSE 0 END AS [M+2]	
    	,CASE WHEN DATEDIFF(MONTH,GETDATE(),d ) = 3 THEN 1 ELSE 0 END AS [M+3]
    FROM LaTable
    GO
     
    SELECT * FROM LaVue
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    d			M-3	M-2	M-1	M	M+1	M+2	M+3
    2011-02-01 00:00:00	0	0	0	0	0	0	0
    2011-05-02 00:00:00	0	0	0	0	0	0	0
    2014-02-03 00:00:00	1	0	0	0	0	0	0
    2014-03-30 00:00:00	0	1	0	0	0	0	0
    2014-05-05 00:00:00	0	0	0	1	0	0	0
    2014-06-06 00:00:00	0	0	0	0	1	0	0
    2014-07-07 00:00:00	0	0	0	0	0	1	0
    2014-08-08 00:00:00	0	0	0	0	0	0	1
    Mais je m'interroge sur le but de tout ça...

  3. #3
    Membre du Club
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Mars 2014
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2014
    Messages : 6
    Par défaut
    Merci beaucoup pour cette solution, j'aime beaucoup la vue

    Et en effet, c'est une modélisation plutôt étrange. Je travaille sur un petit projet de BI, sans cube, le but est de permettre aux utilisateurs d'utiliser des filtres dans leurs rapports prédéfinis permettant de filtrer les chiffres pour juste le mois suivant par exemple. Dans mon framework, je créerait donc un filtre qui ne prendra en compte que les dates dont le booléen M+1 vaudra 1.

    Votre solution fonctionne bien, à ce petit quelque chose près que lorsque je procède de la même manière avec les semaines, le format étant américain, la semaine change entre le samedi et le dimanche. Rien de grave dans la mesure où ces deux journées ne sont pas travaillées.

    Un collègue me suggère d'utiliser DATEADD sinon, pour ou contre?

  4. #4
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    Dans ce cas, pourquoi ne pas simplement faire un filtre sur la date dans la requête ?

    Dans votre exemple, pour filtrer sur les données du mois prochain :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    WHERE LaColonneDate >= 
    	DATEADD(
    		MONTH
    		,DATEDIFF(
    			MONTH
    			,0
    			,GETDATE()
    		) 
    		,0
    	)
    AND LaColonneDate < 
    	DATEADD(
    		MONTH
    		,DATEDIFF(
    			MONTH
    			,0
    			,GETDATE()
    		) + 1
    		,0
    	)
    Le principal avantage étant que les index sur la colonne Date pourront être utilisés.

  5. #5
    Membre du Club
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Mars 2014
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2014
    Messages : 6
    Par défaut
    En fait je travaille avec Cognos et je crains une perte de performance si je fais mes jointures avec des fonctions au lieu de simplement tester la valeur d'un bit, non?

  6. #6
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    Ce n'est pas une jointure, c'est juste un filtre.

    Par ailleurs, les fonctions utilisées n'inclue pas de colonne de la table, c'est pourquoi je disais que les index pourraient être utilisés.

    Les résultats des deux DATEADD seront calculés une seule fois chacun pour la requête, et ensuite les lignes correspondantes pourront être recherchées dans un index adéquat s'il existe. Ce sera donc plutôt positif au niveau des performances.

    En revanche, si vous utilisez la vue que j'avais indiquée plus haut, le critère de recherche deviendra :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    DATEDIFF(MONTH,GETDATE(),d ) = 1
    Dans ce cas, la colonne date est inclue dans la fonction, et l'utilisation d'index ne sera pas possible.

    Enfin, si vous repartez sur votre solution initiale avec les vraies colonnes dans une table, il vous faudra poser un index par colonne, ce qui risque d'être contre performant a terme, surtout qu'il seront fortement fragmentés lors de chaque mise à jour quotidienne...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. quel est le meilleur algo pour table de routage
    Par boboss123 dans le forum Algorithmes et structures de données
    Réponses: 6
    Dernier message: 09/05/2012, 17h36
  2. Pb: Quels privileges pour table partitionnée ?
    Par krilas dans le forum Administration
    Réponses: 4
    Dernier message: 25/10/2010, 12h55
  3. Réponses: 0
    Dernier message: 04/04/2010, 02h48
  4. Réponses: 9
    Dernier message: 08/08/2009, 23h32
  5. Réponses: 6
    Dernier message: 05/06/2008, 11h22

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo