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

Autres SGBD Discussion :

[Teradata] Pour un enregistrement valide sur 3 jours, récupérer 3 enregistrements


Sujet :

Autres SGBD

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    259
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 259
    Points : 97
    Points
    97
    Par défaut [Teradata] Pour un enregistrement valide sur 3 jours, récupérer 3 enregistrements
    Bonjour à tous,

    J'ai une table avec 3 champs :
    - Num_Compte
    - Date
    - Montant

    Num_Compte DAT Montant
    C1 02/01/2024 5000
    C1 05/01/2024 6000
    C1 06/01/2024 6500

    Un nouvel enregistrement est créé lorsque le montant change, et seulement lorsque ce montant change.

    Je souhaiterais, à partir d'une requête SQL, avoir une ligne par jour, et avoir le montant correspondant pour chaque ligne. La requête me renverrait :
    Num_Compte DAT Montant
    C1 02/01/2024 5000
    C1 03/01/2024 5000
    C1 04/01/2024 5000
    C1 05/01/2024 6000
    C1 06/01/2024 6500

    J'ai bien sûr simplifié le problème parce que :
    - je peux avoir plusieurs comptes dans la table
    - la table contient d'autres champs
    - un nouvel enregistrement n'est pas uniquement dû au changement de montant

    L'objectif est d'avoir une ligne par jour, et de reprendre les données de la ligne qui fait foi sur ce jour (DAT précédente).
    Pourriez-vous m'assister, me donner des pistes pour y parvenir ?

    Je vous remercie pour votre aide.

  2. #2
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 080
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 080
    Points : 30 803
    Points
    30 803
    Par défaut
    Bonjour ,

    Qu'as-tu déjà testé comme requête(s) ?
    Où rencontres-tu un problème ?
    • Une erreur d'exécution ? Quel est le message associé ?
    • Un résultat erroné ? Quel est le résultat obtenu ? Le résultat attendu ? Avec quelles données ?
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  3. #3
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 136
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 136
    Points : 38 912
    Points
    38 912
    Billets dans le blog
    9
    Par défaut
    Je ne connais pas Teradata, voici donc une solution applicable sur la plupart des SGBD (testé et validé sur SQL server) et à adapter au votre

    Code SQL : 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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
     
    -- crétion d'un jeu d'essai avec deux comptes
    with tab(cpt, dte, mnt) as
        (select 'C1', cast('2024-01-02' as date), 5000   union all
         select 'C1', cast('2024-01-05' as date), 6000   union all
         select 'C1', cast('2024-01-06' as date), 6500   union all
         select 'C2', cast('2024-01-01' as date), 1500   union all
         select 'C2', cast('2024-01-04' as date), 2100   union all
         select 'C2', cast('2024-01-06' as date), 1800
        )
    -- création d'un calendrier de quelques dates contigues
       , cal(dte, seq) as
        (select min(dte)
              , 1
         from tab
         union all
         select dateadd(day, 1, dte)
              , seq + 1
         from cal
         where seq < 10
        )
    -- combinaison de toutes les dates pour tous les comptes  
       , dtx (cpt, dte) as
        (select distinct 
                tab.cpt
              , cal.dte
         from tab
         cross join cal
        )
    -- et enfin, requête pour "boucher les trous" (reprise du montant de la date qui précède)
    select * from (
      select dtx.cpt  as compte
           , dtx.dte  as datex
           , case when tab.mnt is not null then tab.mnt 
                  else (select T1.mnt
                        from tab T1  
                        where T1.cpt = dtx.cpt
                          and T1.dte = (select max(dte)
                                        from tab T2
                                        where T2.cpt=T1.cpt
                                          and T2.dte<dtx.dte
                                       )
                       )
             end as montant
      from dtx   
      left join tab
         on tab.cpt=dtx.cpt
        and tab.dte=dtx.dte
      where dtx.dte <= (select max(dte) from tab)
                  ) subq
    where subq.montant is not null  
    order by 1, 2


    Résultat :

    Nom : Sans titre.png
Affichages : 92
Taille : 7,4 Ko


    Notes :
    • dans les tables, il n'y a pas de champs, il y a des colonnes, les champs sont les zones des formulaires de saisie ou des états
    • il est préférable de coder les dates au format iso, c'est à dire 'CCAA-MM-JJ', plutôt que 'JJ/MM/CCAA'

  4. #4
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    J'ai quelques remarques:
    1. Pourquoi voulez-vous passer d'un stockage à peu près optimisé à une version dégradée qui sera plus coûteuse en terme de place ?
    2. Pourquoi n'utilisez-vous pas une table temporelle qui effectue la tâche "insérer la donnée que si la valeur change" nativement ?


    Il y a deux façons propres à TD de répondre à votre question, mais je n'ai rien pour tester donc ça nécessitera certainement quelques ajustements.
    1. Expand on
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    select Num_Compte, begin(expd) as DAT, Montant
      from MaTable
    expand on period(DAT , lead(DAT) over(partition by Num_Compte order by DAT asc)) as expd
        by interval '1' day;
    2. Group by time attention aux time zone
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
      select Num_Compte
           , cast(begin($TD_TIMECODE_RANGE) as date at 0) as DAT
           , sum(Montant) as Montant
        from MaTable
    group by time(cal_days(1) and Num_Compte)
       using timecode(DAT)
        fill (PREV);
    Je rappelle que ce code est non testé.

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    259
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 259
    Points : 97
    Points
    97
    Par défaut
    Bonjour à tous,

    Tout d'abord, merci pour toutes vos réponses et pour que le temps que vous avez consacré à me répondre.

    J'ai commencé par regarder la proposition de @Waldar, qui me semble la plus simple à appliquer.

    J'ai quelques remarques:
    Pourquoi voulez-vous passer d'un stockage à peu près optimisé à une version dégradée qui sera plus coûteuse en terme de place ?
    Pourquoi n'utilisez-vous pas une table temporelle qui effectue la tâche "insérer la donnée que si la valeur change" nativement ?
    Il ne s'agit pas d'une solution qui me permette de stocker les données. Je dois calculer lorsque le montant dépasse un autre montant, en fonction de plusieurs dates et si je n'ai pas d'enregistrement jour à jour, je ne sais pas m'en sortir.

    J'ai adapté la 2e requête et elle fonctionne à merveille ! J'ai seulement dû ajouter 1 jour pour que ça colle parfaitement à ma table :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT CLE_TABLE 
           , Cast(Begin($Td_TimeCode_Range) AS DATE AT 0)  + INTERVAL '1' DAY AS DAT
           , Sum(MT_ENCRS_RETENU) AS MONTANT1
    	   , Sum(MT_AUTR_EUR_RETENU) AS MONTANT2
        FROM MA_TABLE A
    	WHERE CLE_TABLE = 447413705
    GROUP BY TIME(Cal_Days(1) AND CLE_TABLE )
       USING timecode(DAT)
        FILL (PREV);
    J'ai fait quelques recherches google pour essayer de comprendre comment ça fonctionne mais je n'ai rien trouvé de clair. Est-ce qu'il serait possible de me transmettre un lien qui me donne des explications ? Je n'arrive pas à comprendre comment la requête fait le lien entre DAT et la date de ma table.
    Franchement, merci beaucoup, je ne pensais pas avoir une solution aussi facile à appliquer !!

  6. #6
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Je pensais que la première solution serait la plus simple à adapter, mais l'important c'est que ça fonctionne.

    GROUP BY TIME est une extension spécifique à Teradata permettant de travailler sur les time series, c'est arrivé en v16.
    Tout le chapitre est ici :
    https://docs.teradata.com/r/Enterpri...and-Operations

    Mais sur le GROUP BY TIME spécifiquement c'est ici :
    https://docs.teradata.com/r/Enterpri...ECT-Extensions

    Pour le jour en plus à la table, c'est probablement une histoire de time zone, essayez sans le +1 jour mais avec Cast(Begin($Td_TimeCode_Range) AS DATE AT 'Europe Central').

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    259
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 259
    Points : 97
    Points
    97
    Par défaut
    Merci Waldar,

    C'est vrai, la première solution est beaucoup plus simple à appliquer et m'éviterait de mettre des Sum sur tous les montants et des Min ou Max sur tous les autres champs.

    Je ne l'ai pas prise dans un premier temps parce que je rencontre un problème :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT 
    	  A.MaPK 
    	, Begin(expd) AS DAT
    	, A.DAT
    	, A.Montant1
    	, A.Montant2
      FROM MaTable A
     WHERE A.MaPK = 447413705
    EXPAND ON PERIOD(A.DAT , Lead(A.DAT) Over(PARTITION BY A.MaPK ORDER BY A.DAT ASC)) AS expd 
    BY INTERVAL '1' DAY
    En fait, dès que je mets le "expd" dans les champs du SELECT, j'obtiens l'erreur suivante :
    SELECT Failed. (-9307) Invalid use of the expanded column name.
    Teradata me dit ceci : https://docs.teradata.com/r/Teradata...-Messages/9306

    This error is reported if the expanded column name is specified in any other clause other than ORDER BY clause and in any expression in the projection list or ORDER BY clause.
    J'ai beau le retourner dans tous les sens, je ne comprends pas ce que je dois faire pour pouvoir l'afficher dans mon SELECT. Est-ce que je peux abuser une dernière fois de ton aide ?

    Merci beaucoup !!

  8. #8
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Il faudrait voir la requête complète pour voir où se situe l'erreur, mais en effet l'usage de expd (la période d'expansion) est soumis à quelques règles.
    N'hésitez pas à utiliser une CTE pour calculer cette valeur et ensuite l'utiliser.

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

Discussions similaires

  1. [2K8] Pb pour calculer la CA N-1 sur un jour donné
    Par EricOppessios dans le forum SSAS
    Réponses: 7
    Dernier message: 11/02/2011, 14h10
  2. [AC-2007] Lien hypertexte pour ouvrir une BDD sur un enregistrement précis
    Par Lincoln911 dans le forum VBA Access
    Réponses: 0
    Dernier message: 03/08/2010, 10h10
  3. Réponses: 1
    Dernier message: 10/02/2009, 21h30
  4. Requête pour les rappel sur 5 jour
    Par Mbrillon dans le forum Oracle
    Réponses: 16
    Dernier message: 06/05/2007, 14h01
  5. Réponses: 7
    Dernier message: 05/01/2007, 14h14

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