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 :

[MSSQL2k5] Fonctionnement de ISNULL ?


Sujet :

MS SQL Server

  1. #1
    Membre habitué Avatar de mioux
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Novembre 2005
    Messages
    367
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2005
    Messages : 367
    Points : 191
    Points
    191
    Par défaut [MSSQL2k5] Fonctionnement de ISNULL ?
    Salut

    J'ai un petit problème de compréhension face à ISNULL()

    Je viens de poser une rustine sur un programme car SQL Server me renvoit un NULL sur une requette où j'ai spécifié un ISNULL(Col, -1)

    J'ai lu le cours sur le NULL de SQLPro (qui m'a bien embrouillé sur ce qu'est NULL ) situé ici http://sqlpro.developpez.com/cours/null/ et la doc MSDN sur ISNULL (qui elle est ici http://msdn2.microsoft.com/en-us/lib...0(SQL.80).aspx)

    En fait je cherche à comprendre quand est ce qu'un SELECT ISNULL(Tb.Col, -1) peut me renvoyer NULL sachant que dans mon FROM il y a des jointures externes sur ladite colone

    PS : Non je ne suis pas un adepte du "pas de NULL", mais mon prédécesseur lui oui, et en plus il est adepte de "je met le moins de jointure possible et je duplique la donnée" histoire que quand on a besoin de chercher des cas particuliers, on peut pas les isoler, mais ca c'est une autre histoire

    PPS : Je ne peux pas vous donner la requette car déjà bien tordue et remplie de rustines elle aussi (et surtout, je pense pas que le client apprécirait trop qu'on divulgue une partie de ses données)

    EDIT : et PPPS : Oui j'ai aussi essayé ISNULL(ISNULL(Tb.Col, -1), -1) . Rien qu'en l'écrivant ça me paraissait débile

  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
    21 852
    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 : 21 852
    Points : 52 992
    Points
    52 992
    Billets dans le blog
    6
    Par défaut
    C'est votre jointure externe qui ramene des NULL.

    Postez votre requête intégralement.

    A +

  3. #3
    Membre habitué Avatar de mioux
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Novembre 2005
    Messages
    367
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2005
    Messages : 367
    Points : 191
    Points
    191
    Par défaut
    Justement j'étais en train de me demander comment la poster sans montrer les données sensibles... et je me rends compte qu'il n'y en a presque pas

    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    SELECT DISTINCT TB1.THEME_LIBELLE,
          TB1.FER_ID,
          TB1.FER_LIBELLE,
          TB1.AFFAIRE_ID,
          TB1.ACTIVITE_ID,
          TB1.THEME_ID,
          CASE WHEN TB1.EVAL_ID <> -1 THEN TB2.EVAL_ID ELSE -1 END AS EVAL_ID,
          ISNULL(TB2.NUMERATEUR, 0) AS NUMERATEUR,
          ISNULL(TB2.DENOMINATEUR, 1) AS DENOMINATEUR
    FROM (SELECT TBL_THEME.THEME_LIBELLE, TBL_FER.FER_ID, TBL_FER.FER_LIBELLE, LNK_AFFAIRE_EVAL_ACTIVITE.AFFAIRE_ID,
                LNK_AFFAIRE_EVAL_ACTIVITE.ACTIVITE_ID, TBL_THEME.THEME_ID, ISNULL(TBL_AUTORIZE_PA.EVAL_ID, -1) AS EVAL_ID
        FROM PER4_Monde_Dev.dbo.LNK_AFFAIRE_EVAL_ACTIVITE LNK_AFFAIRE_EVAL_ACTIVITE INNER JOIN
             PER4_Monde_Dev.dbo.LNK_ACTIVITE_FER LNK_ACTIVITE_FER ON LNK_AFFAIRE_EVAL_ACTIVITE.ACTIVITE_ID = LNK_ACTIVITE_FER.ACTIVITE_ID INNER JOIN
             PER4_Monde_Dev.dbo.LNK_THEME_FER LNK_THEME_FER ON LNK_ACTIVITE_FER.FER_ID = LNK_THEME_FER.FER_ID INNER JOIN
             PER4_Monde_Dev.dbo.TBL_THEME TBL_THEME ON LNK_THEME_FER.THEME_ID = TBL_THEME.THEME_ID INNER JOIN
             PER4_Monde_Dev.dbo.TBL_FER TBL_FER ON LNK_ACTIVITE_FER.FER_ID = TBL_FER.FER_ID LEFT OUTER JOIN
             PER4_Monde_Dev.dbo.TBL_AUTORIZE_PA TBL_AUTORIZE_PA ON TBL_AUTORIZE_PA.FER_ID = TBL_FER.FER_ID AND TBL_AUTORIZE_PA.AFFAIRE_ID = '75614224'
        WHERE LNK_AFFAIRE_EVAL_ACTIVITE.EVAL_ID IN (-1, 8394, 8395)
              AND TBL_FER.LANGUE_ID = 1
              AND TBL_THEME.LANGUE_ID = 1) AS TB1
        LEFT OUTER JOIN
        (SELECT DISTINCT LAF.ACTIVITE_ID, LAEA.AFFAIRE_ID, LTF.THEME_ID, TF.FER_ID, TF.FER_LIBELLE, TT.THEME_LIBELLE,
               SUM(CAST(REPLACE(TRE.PROPOSITION_ID, '2', '0') AS REAL)) AS NUMERATEUR,
               SUM(CAST(REPLACE(TRE.PROPOSITION_ID, '2', '1') AS REAL)) AS DENOMINATEUR,
               ISNULL(MAX(TAP.EVAL_ID), -1) AS EVAL_ID
        FROM PER4_Monde_Dev.dbo.LNK_AFFAIRE_EVAL_ACTIVITE LAEA INNER JOIN
             PER4_Monde_Dev.dbo.TBL_RESULTAT_EVALUATION TRE ON LAEA.EVAL_ID = TRE.EVAL_ID INNER JOIN
             PER4_Monde_Dev.dbo.LNK_FER_QUESTION LFQ ON TRE.QUESTION_ID = LFQ.QUESTION_ID INNER JOIN
             PER4_Monde_Dev.dbo.TBL_FER TF ON LFQ.FER_ID = TF.FER_ID INNER JOIN
             PER4_Monde_Dev.dbo.LNK_THEME_FER LTF ON TF.FER_ID = LTF.FER_ID INNER JOIN
             PER4_Monde_Dev.dbo.LNK_ACTIVITE_FER LAF ON LAF.FER_ID = TF.FER_ID INNER JOIN
             PER4_Monde_Dev.dbo.TBL_THEME TT ON TT.THEME_ID = LTF.THEME_ID LEFT OUTER JOIN
             PER4_Monde_Dev.dbo.TBL_AUTORIZE_PA TAP ON (TAP.AFFAIRE_ID = '75614224' AND (TAP.EVAL_ID IN (-1, 8394, 8395) OR TAP.EVAL_ID IS NULL)AND TAP.FER_ID = TF.FER_ID)
        WHERE (LAEA.AFFAIRE_ID = '75614224')
              AND (TF.LANGUE_ID = 1)
              AND LAEA.EVAL_ID IN (-1, 8394, 8395)
              AND TT.LANGUE_ID = 1
        GROUP BY LAEA.EVAL_ID, TF.FER_ID, TF.FER_LIBELLE, LAF.ACTIVITE_ID, LAEA.AFFAIRE_ID, LTF.THEME_ID, TT.THEME_LIBELLE) AS TB2
        ON TB1.FER_ID = TB2.FER_ID
    WHERE 1 = 1
    ORDER BY TB1.FER_ID
    Le pire c'est qu'avec la facon dont sont organisée les données dans la base, j'ai pas trouvé d'autre moyens de faire que ces 2 sous requettes, sinon ça ne me renvoit jamais ce que je veux

    Soit dit en passant, inutile d'essayer de "corriger" la requette, je cherchais juste la réponse à titre informatif, et ca confirme mes soupçons... Un NULL provenant d'une jointure externe n'est pas remplacé dans un ISNULL. Et je ne m'inquiette pas pour "dans 10 ans" parce que, connaissant le client, d'ici l'an prochain, on casse tout et on recommence (c'est comme ca tout les ans environ)

    EDIT : Je me suis rendu compte qu'il manquait un ISNULL dans le SELECT principal (pour la colone EVAL_ID), du coup ma jointure renvoyait NULL et n'était pas remplacée par -1

    Je craque avec ce genre de trucs

    Et re Edit : C'est dans des cas comme celui ci qu'on voit qu'il manque un DBA dans la boite

    Encore une fois EDIT (je vais y arriver à tout dire) : Je viens aussi de me rendre compte que ce que j'ai dit plus haut
    Un NULL provenant d'une jointure externe n'est pas remplacé dans un ISNULL.
    est faux

  4. #4
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 852
    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 : 21 852
    Points : 52 992
    Points
    52 992
    Billets dans le blog
    6
    Par défaut
    Effectivement il faudrait refactoriser les sous requetes afin de ne plus en avoir (tout à fait possible).
    En outre rempalcez :
    CASE WHEN TB1.EVAL_ID <> -1 THEN TB2.EVAL_ID ELSE -1 END AS EVAL_ID,
    par le contraire :
    CASE WHEN TB1.EVAL_ID = -1 THEN ... ELSE
    de façon à ce que le critère soit sargable.

    Enfin, pensez à ajouter les index adéquats :
    Sur toutes les foreign keys
    sur toutes les conditions de recherches.

    A +

  5. #5
    Membre habitué Avatar de mioux
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Novembre 2005
    Messages
    367
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2005
    Messages : 367
    Points : 191
    Points
    191
    Par défaut
    Merci du conseil pour le case

    Concernant les 2 sous requettes, j'ai cherché un bon moment comment ne pas les faire, mais j'ai fini par abandonner par manque de temps. Normalement cette requette est censée me renvoyer exactement 25 lignes, et quand j'ai commencé à l'écrire, je n'arrivait jamais au résultat que je voulais. Du coup j'ai fais séparément les 2 requettes, et je les ai jointes après.

    Au moins ca fonctionne, et le client est content

    Maintenant quand j'aurai un peu plus de temps je m'y repencherai

Discussions similaires

  1. [AC-2003] IsNull ne fonctionne pas comme souhaité
    Par Dermochelys dans le forum VBA Access
    Réponses: 2
    Dernier message: 25/09/2009, 15h09
  2. [MSSQL2k5] Comment faire un isnull() sur plusieurs champs
    Par tamiii dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 29/07/2008, 11h50
  3. [Turbo Pascal] TP7 fonctionne en QWERTY
    Par callahan dans le forum Turbo Pascal
    Réponses: 9
    Dernier message: 08/02/2003, 21h49
  4. Prb de fonctionnement dans SaveDialog avecInitialDir
    Par boyerf dans le forum Composants VCL
    Réponses: 4
    Dernier message: 12/12/2002, 21h46
  5. ca ne fonctionne pas (generateur auto-incrémentant)
    Par tripper.dim dans le forum SQL
    Réponses: 7
    Dernier message: 26/11/2002, 00h10

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