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

Développement SQL Server Discussion :

LAG si NULL récursif


Sujet :

Développement SQL Server

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2009
    Messages : 3
    Par défaut LAG si NULL récursif
    Bonjour

    Je suis sous SQL Server Express 2012.

    Mon problème est le suivant:

    Considérons que j'ai une table Historique( IDGroupe uniqueidentifier, Date datetime, Montant money ).

    Pour une raison particulière, certains Montant ont une valeur NULL. Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    1    1/1/2012    12556
    2    1/2/2012    -null-
    3    1/3/2012    -null-
    4    1/5/2012    5478
    5    1/6/2012    -null-
    Je voudrais que les valeurs NULL prennent la valeur du premier non NULL précédent. A partir de la table précédente, j'aimerais obtenir le résultat suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    1    1/1/2012    12556
    2    1/2/2012    12556
    3    1/3/2012    12556
    4    1/5/2012    5478
    5    1/6/2012    5478

    Au début j'ai pensé utiliser LAG de la sorte :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT 
        ID, 
        Date, 
        COALESCE( Montant, LAG(Montant) OVER (ORDER BY IDGroupe, Date) ) Montant 
    FROM Historique
    Cependant, je me retrouve avec le résultat suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    1    1/1/2012    12556
    2    1/2/2012    12556
    3    1/3/2012    -null-
    4    1/5/2012    5478
    5    1/6/2012    5478
    J'ai l'impression que LAG intervient après que les données furent collectées. Je veux dire qu'il me semble que pour la première ligne, vu que Montant n'est pas égal à NULL, celui-ci est bien repris. Que le second Montant étant, lui, égal à NULL prend la valeur de l'enregistrement précédent suivant la clause ORDER BY. Mais que le troisième, ayant aussi une valeur NULL, devrait se voir attribuer la valeur de l'enregistrement précédent suivant la clause ORDER BY. Or, cet enregistrement précédent semble toujours contenir NULL au lieu de la valeur précédemment attribuée (c'est-à-dire la valeur de la première ligne).

    Quelqu'un pourrait m'expliquer où je me trompe ?

    D'avance merci

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    22 002
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 22 002
    Billets dans le blog
    6
    Par défaut
    C'est normal que vous ayez un NULL, puisque LAG considère la ligne d'avant...
    Pour faire cela utilisez une sous requête corrélée.

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  3. #3
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    La question n'est pas idiote puisque la fonction LAG existe chez la concurrence avec l'option IGNORE NULLS, qui n'est pas implémentée chez SQL-Server.

    Essayez comme ceci :
    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
    With Historique (IDGroupe, DateHisto, Montant) as
    (
    select 1, '2012-01-01', 12556 union all
    select 2, '2012-01-02', null  union all
    select 3, '2012-01-03', null  union all
    select 4, '2012-01-05', 5478  union all
    select 5, '2012-01-06', null
    )
      ,  SR (IDGroupe, DateHisto, Montant, Part) as
    (
    select IDGroupe, DateHisto, Montant
         , sum(case when Montant is null then 0 else 1 end) over(order by IDGroupe asc)
      from Historique 
    )
    select IDGroupe, DateHisto
         , max(Montant) over(partition by part)
      from SR
     order by 1;

  4. #4
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2009
    Messages : 3
    Par défaut [RESOLU] LAG si NULL récursif
    Citation Envoyé par SQLpro Voir le message
    C'est normal que vous ayez un NULL, puisque LAG considère la ligne d'avant...
    Pour faire cela utilisez une sous requête corrélée.

    A +
    Ce n'est pas aussi normal que vous le dites. En tout cas dans mon esprit. La question théorique sous-jacente était : est-ce que le LAG se base sur la valeur du ROW précédent avant ou après que le LAG du ROW précédent ait été effectué.

    En d'autres mots, est-ce que la fonction analytique LAG se base sur une table virtuelle dont les valeurs calculées sont modifiées en séquence ou sur une table fictive dont les valeurs calculées ne sont pas modifiées.

    Démonstration avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT 
        ID, 
        Date, 
        COALESCE( Montant, LAG(Montant) OVER (ORDER BY IDGroupe, Date) ) Montant_C
    FROM Historique
    1) Les lignes nécessaires sont collectées dans une table fictive (peut-être uniquement les références d'index pour optimisation)
    2) De la présence du LAG, le code de traitement analyse et le champ calculé Montant_C
    A) La ligne 1 est analysée
    i) Montant n'est pas NULL, ce sera sa valeur qui résultera dans Montant_C
    B) La ligne 2 est analysée
    i) Montant est NULL, la procédure "parcourt dans un ordre précis" afin de trouver la ligne précédente à l'actuelle dans cet ordre. Ici, la valeur de Montant à la ligne 1.
    C) La ligne 3 est analysée
    i) Montant est NULL, la procédure "parcourt dans un ordre précis" afin de trouver la ligne précédente à l'actuelle dans cet ordre. Ici, arrive ma question est la valeur Montant_C ou la valeur Montant de la ligne 2 qui sera utilisé. Autrement dit, est-ce la valeur NULL ou 12556 qui sera pris.

    Je crois que je réponds à ma question dans ma post-réflexion suivante: "L'ordre de traitement des lignes n'est pas garanti en séquence sur l'ordre logique qu'on attend. Il est dès lors impossible de garantir que la ligne x-1 soit absolument traitée avant la ligne x. Donc, il se peut que la ligne x conserve une valeur NULL tout autant quelle peut avoir une nouvelle valeur calculé. Si l'état n'est pas garanti, il ne peut être fiable et doit être interdit."

    Waldar, je crois qu'il y a une mésentente sur le terme IDGroupe - que j'ai mal formulé, bien entendu Cependant, je vais regarder à votre solution pour en extraire l'essence. Cela pourrait me fournir une méthode de pensée inédite dans mon univers

    Par ailleurs, jouant avec des trimestres, j'ai finalement opté pour une suite de 4 LAG en cherchant le premier des 4 montants précédents qui ne soit pas NULL. Il est garanti qu'un trimestre ait un montant. Or, je garde votre réponse sous le bras, si ça peut me permettre de faire gagner quelques précieuses secondes à mon directeur.


    En tout cas merci à vous deux pour avoir fait attention à mon post et d'avoir pris du temps à me répondre.

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

Discussions similaires

  1. PROBLEME AVEC LES REQUETES IS NULL / NOT EXISTS
    Par sylvaine dans le forum Langage SQL
    Réponses: 5
    Dernier message: 04/06/2004, 13h26
  2. Comment rediriger la sortie vers /dev/null
    Par dclink dans le forum C
    Réponses: 4
    Dernier message: 24/06/2003, 18h23
  3. Tester si un champ est NULL
    Par titititi007 dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 19/06/2003, 10h17
  4. [VB6] [BDD] Recordset et champ égal à Null
    Par Gr|ppen dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 07/03/2003, 10h00
  5. "ALTERER" une col. NULL en NOT NULL - Int
    Par Gandalf24 dans le forum SQL
    Réponses: 2
    Dernier message: 28/12/2002, 00h07

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