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

Schéma Discussion :

[FN]entre la theorie et la pratique!


Sujet :

Schéma

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    551
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2005
    Messages : 551
    Points : 260
    Points
    260
    Par défaut [FN]entre la theorie et la pratique!
    bonjour,

    j'ai une table : bienHistorique

    IDBienHistorique (clef primaire)
    Id (clef etrangere)
    histoDateModif
    histoPrix
    histoAnnonce
    histoCommunication

    pour chaques tuples, soit "histoPrix",soit "histoAnnonce", soit "HistoCommunication" est renseigné.
    Rarement "histoPrix" et "HistoAnnonce" sont renseigné sur le meme tuple

    Je sais que theroiquement, il aurait plutot fallut faire deux table

    bienHistorique 1,1 ---------------- 0,n bienTypeHisto
    IDBienHistorique (clef primaire) ---------- idBienTypeHistorique
    id (clefEtangere) ------------------------valeurHisto
    histoDateModif
    idBienTypeHistorique (clefEtangere)

    Nous aurions donc 3 enregistrements pour "bienTypeHisto".
    la "valeurHisto" de "bienTypeHisto" serait
    *histoPrix
    *histoAnnonce
    *HistoCommunication

    A ce jour, ce n'est pas prevu du tout que nous ayions plus d'enregistrement dans cette derniere table.

    ma question est :

    Faut il appliquer ce que la theorie m'a appris, ou je garde ma table de depart?
    est ce que cela vaut la peine de creer une table pour 3 enregistrements?
    Ma bdd n'est elle pas plus performante dans l'etat actuel qu'elle ne pourrait l'etre comme l'exige la theorie??

    j'espere que vous avez tout compris,car suis pas sure d'etre tres claire

    merci
    nath

  2. #2
    Rédacteur/Modérateur

    Avatar de Fabien Celaia
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Octobre 2002
    Messages
    4 222
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Service public

    Informations forums :
    Inscription : Octobre 2002
    Messages : 4 222
    Points : 19 554
    Points
    19 554
    Billets dans le blog
    25
    Par défaut
    Normalisez si vous pouvez
    Ne dénormalisez que pour des raisons de performance.
    Sr DBA Oracle / MS-SQL / MySQL / Postgresql / SAP-Sybase / Informix / DB2

    N'oublie pas de consulter mes articles, mon blog, les cours et les FAQ SGBD

    Attention : pas de réponse technique par MP : pensez aux autres, passez par les forums !

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    551
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2005
    Messages : 551
    Points : 260
    Points
    260
    Par défaut
    et dans mon cas, on aurait de meilleurs performance en normalisant ou en denormalisant?

  4. #4
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 001
    Points : 30 905
    Points
    30 905
    Billets dans le blog
    16
    Par défaut
    Bonjour Nath,

    Citation Envoyé par Nath
    Je sais que theroiquement, il aurait plutot fallut faire deux table
    De quelle théorie parlez-vous ? S’il s’agit de l’approche entité/relation, il n’y a pas de théorie. S’il s’agit de la théorie relationnelle, sachez qu’elle n’impose rien à ce sujet. La seule recommandation qu’elle fait et qui peut vous concerner ici, touche aux valeurs nulles, interdites de séjour. Si vous pensez à SQL, il n’y a pas de théorie SQL.


    Citation Envoyé par Nath
    Ma bdd n'est elle pas plus performante dans l'etat actuel qu'elle ne pourrait l'etre comme l'exige la theorie??
    Ne mélangez pas le niveau logique et le niveau physique : très nombreux sont ceux qui ont oublié que l’indépendance entre le niveau physique et le niveau logique est un point capital et se sont fourvoyés. Commencez par vous focaliser sur le niveau logique. Quant à la performance (niveau physique), on trouve toujours un moyen de la garantir sans dénaturer ce qui a été fait au niveau logique.

    Pour tordre le cou aux valeurs nulles, votre solution consistant à mettre en œuvre la table bienTypeHisto est préférable. Vous pouvez aussi éviter de mettre en œuvre cette table au profit d’une contrainte au niveau de l’attribut idBienTypeHistorique :

    Create Table bienTypeHisto ( ...,
    ____idBienTypeHistorique Char(n) Constraint CKxyz
    ______Check (ConstraintidBienTypeHistorique In ("histoPrix", " histoAnnonce", "histoComm")),
    _____________________... ) ;

    Remarque : avez-vous prévu de conserver la valeur de la donnée historisée ?

    Toujours en prenant soin de ne pas vous focaliser tout de suite sur l’aspect performance, vous pouvez aussi remplacer la table bienTypeHisto par 3 tables : PrixHistorique, AnnonceHistorique et CommunicationHistorique, solution la plus propre, surtout si vous gardez trace de la valeur à date de la donnée historisée.

    Pour en arriver au niveau physique. Quant à la performance en relation aves le fait de normaliser ou dénormaliser, il n'y a aucune règle absolue. Vous devez construire un prototype, mesurer cette performance et améliorer le paramétrage physique (à commencer par les index...) jusqu’à obtenir les performances attendues. Sachez qu'en vingt ans de ("very large") bases de données relationnelles dans tous les secteurs d'activité, banque, assurance, industrie, services, j'en passe et des meilleures, j'ai toujours normalisé à fond et n'ai jamais eu à dénormaliser. En contrepartie, j'ai prototypé des nuits et des nuits (pour ne pas perturber les autres en pleine journée) et j'ai retenu que rien n'est jamais acquis : ce qui marche bien chez l'un est à reprendre complètement chez l'autre, et c'est ce qui fait du reste un des charmes du métier...
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  5. #5
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 760
    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 760
    Points : 52 541
    Points
    52 541
    Billets dans le blog
    5
    Par défaut
    Sachez qu'en vingt ans de ("very large") bases de données relationnelles dans tous les secteurs d'activité, banque, assurance, industrie, services, j'en passe et des meilleures, j'ai toujours normalisé à fond et n'ai jamais eu à dénormaliser. En contrepartie, j'ai prototypé des nuits et des nuits (pour ne pas perturber les autres en pleine journée) et j'ai retenu que rien n'est jamais acquis : ce qui marche bien chez l'un est à reprendre complètement chez l'autre, et c'est ce qui fait du reste un des charmes du métier...
    Tiens il faudrait rajouter cela à la discusion que nous avons eu sur la dénormalisation :
    http://www.developpez.net/forums/showthread.php?t=6231

    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/ * * * * *

  6. #6
    Membre actif
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    551
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2005
    Messages : 551
    Points : 260
    Points
    260
    Par défaut
    en fait je parlais de ce qu'on nous avait appris a l'ecole , sur la maniere de realiser une base de donnée logique..

    il faut eviter les valeurs NULL?pourquoi? a part que cela incombre inutilement la base?
    dans une de mes tables, j'ai bcp de valeurs NULL, car j'ai deja bcp de champs, et tous ne sont pas forcement renseigné( j'ai une table BIEN avec toutes les caracteristique que peut bien avoir un appartement,une maison)

    Oui j'ai prevu de conserver les historiques...

    vous pouvez aussi remplacer la table bienTypeHisto par 3 tables : PrixHistorique, AnnonceHistorique et CommunicationHistorique, solution la plus propre, surtout si vous gardez trace de la valeur à date de la donnée historisée.
    En quoi est ce plus propre que :
    BienHisto
    >idBienHisto
    >idBienTypeHisto
    >dateHisto

    et

    bientypeHisto
    >idBienTypeHisto
    >LibelleTypeHisto

    merci pour vos commentaire!!

  7. #7
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 001
    Points : 30 905
    Points
    30 905
    Billets dans le blog
    16
    Par défaut
    Bonsoir Nath,

    Citation Envoyé par Nath-0-0
    en fait je parlais de ce qu'on nous avait appris a l'ecole , sur la maniere de réaliser une base de donnée logique.
    Hum... Je ne sais si c’est l’élève qui a mal compris. En tout cas, retenez bien qu’il ne faut pas mélanger les niveaux. Le logique est le physique ne doivent pas être imbriqués, au risque de prendre de terribles gamelles.


    Citation Envoyé par Nath-0-0
    il faut éviter les valeurs NULL? Pourquoi?
    Si vous le voulez bien, situons-nous au niveau logique. Vous utilisez SQL. Or, ce langage a été conçu pour partie à partir de l’algèbre relationnelle et pour partie à partir du calcul relationnel tous deux définis par l’inventeur du Modèle relationnel, Ted Codd, mathématicien, logicien et génie. Le calcul relationnel est une alternative à l’algèbre relationnelle et il est basé sur une branche de la mathématique logique, appelée calcul des prédicats. Or, en logique, les énoncés que nous formulons sont vérifonctionnels, c’est-à-dire qu’ils sont soit vrais, soit faux.

    Par exemple (à vous de juger de la vérité ou de la fausseté) :

    « Tous les développeurs qui fréquentent développez.com gagnent au moins 4000 euros par mois ».

    « Il existe des développeurs qui fréquentent développez.com et gagnent au moins 4000 euros par mois ».

    Cette logique est binaire et on lui associe des tables de vérité permettant de prédire le résultat, vrai ou faux, de la combinaison d’énoncés à l’aide des connecteurs logiques ET, OU, NON. Vous savez que si une proposition est vraie, sa négation est fausse. Si deux propositions sont vraies ensemble, leur conjonction l’est également, etc.

    Le problème avec SQL (qui est donc basé en partie sur la logique) est qu’en plus d’être vrai ou faux, le sens d’une proposition peut être considéré comme inconnu. On se retrouve avec une logique à 3 états : "vrai", "faux", "inconnu". Cet inconnu (unknown) est encore appelé NULL. Concernant les tables de vérité, voyez par exemple :

    http://www.ianywhere.com/developer/p...9/00000039.htm.

    Dans un tel contexte, si A = 3, B = 4 et C inconnu :

    A < B OU B < C est vrai
    A > B OU B > C est inconnu

    Ça n’est pas intuitif, mais conforme aux tables de vérité.

    De la même façon, A < 1 OU A = 1 OU A > 1 n’est plus une tautologie.

    Appliqué à l’arithmétique : A + inconnu = inconnu. Si donc vous calculez le total des salaires de votre entreprise et qu’un salaire est NULL, le total est NULL. Si parmi vos propres éléments de salaire un élément est NULL, votre salaire sera NULL, ce qui ne sera pas pour vous arranger, mais NULL est un tyran et un traître qui se moque de vous.

    En conclusion, les NULLs peuvent encore être perçus comme des sables mouvants qui vous attendent. SQL n’est pas très regardant et vous laisse vous débattre et passer votre temps à combiner des IS NOT NULL associés avec toutes les colonnes pouvant prendre la valeur NULL.

    => NULL = Dynamite...

    Le mieux est de modéliser de telle sorte que l’on n’ait pas à s’y frotter, surtout quand on n’est pas artificier.


    Dans votre premier message, vous écrivez :
    Rarement "histoPrix" et "HistoAnnonce" sont renseigné sur le même tuple
    Donc ceci est source de NULL.

    Par contre, quand bous écrivez :
    En quoi est ce plus propre que :
    BienHisto
    >idBienHisto
    >idBienTypeHisto
    >dateHisto

    et

    bientypeHisto
    >idBienTypeHisto
    >LibelleTypeHisto
    Je répondrai donc que si les tous attributs de ces 2 tables sont déclarés NOT NULL, pas de problème !
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  8. #8
    Expert éminent sénior

    Avatar de Tofalu
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Octobre 2004
    Messages
    9 501
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Octobre 2004
    Messages : 9 501
    Points : 32 311
    Points
    32 311
    Par défaut
    Bonjour,

    @fsmrel, il y a quand même quelque chose qui me choque dans votre approche. je vous trouve un peu trop catégorie dans votre affirmation quant aux null.

    Dans un SI, on se retrouve toujours avec des données optionnelles.

    Prenons le cas que vous citez :

    « Tous les développeurs qui fréquentent développez.com gagnent au moins 4000 euros par mois ».

    Nous avons donc notre table Visiteurs(id, pseudo, salaire).

    La morale (qui peut être ici assimilée à une contrainte de gestion) me force à donner le choix à mes visiteurs de renseigner leur salaire ou pas. Je ne peux donc pas interdire les valeurs nulles pour le salaire. Certes je me situe ici au niveau physique mais au niveau logique mon entité et mes attributs seraient les mêmes. Ou alors me conseilleriez vous d'avoir une table des salaires ?

  9. #9
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 001
    Points : 30 905
    Points
    30 905
    Billets dans le blog
    16
    Par défaut
    Bonsoir,

    Citation Envoyé par Tofalu
    @fsmrel, il y a quand même quelque chose qui me choque dans votre approche. je vous trouve un peu trop catégorie dans votre affirmation quant aux null.
    Je comprends que vous soyez choqué. Je suis certes catégorique, mais je ne peux pas non plus recommander le laxisme face aux pièges tendus par la logique ternaire appliquée aux bases de données et en particulier par SQL en particulier avec ses "valeurs" nulles.


    Citation Envoyé par Tofalu
    Dans un SI, on se retrouve toujours avec des données optionnelles.
    Je suis bien d’accord avec vous ! Mais il peut y avoir plusieurs façons d’aborder le problème délicat de l’absence d’information.


    Citation Envoyé par Tofalu
    alors me conseilleriez vous d'avoir une table des salaires ?
    Certes. Je suis d’accord que cela fait une table de plus à chaque fois que la situation se présente, disons dans le cas des données de type numérique, tel le salaire. Pour les données de type chaînes de caractères, on peut l’éviter, avec par exemple une valeur par défaut à SPACE. Pour un salaire, les valeurs sont malheureusement toutes significatives...


    Vous proposez la table Visiteur (Id, Pseudo, Salaire), pour laquelle le salaire n’est pas nécessairement renseigné, par exemple parce qu’on ne le connaît pas encore (mais ça viendra plus tard), ou bien parce pour la personne, la notion de salaire ne s’applique pas, ou bien parce qu’elle refuse de le préciser, ou que sais-je encore. Pour tous ces cas de figure, on est conduit à utiliser la valeur nulle, laquelle sert pour tous ces cas de figure (ce qui n’est pas forcément satisfaisant).

    Exemple (avec en prime les primes) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        id	 Pseudo   Salaire   Prime
        e1	 Jeannot   2000      200
        e2	 Sergio    1500      300
        e3	 Gillou	   1500     null
        e4	 Nanou	   null      200
        e5	 Riton	   null        0 
        e6	 Nanard	   1000     null
    
                  Figure 1
    (Concernant les primes : Tout le monde n’y a pas droit. Riton y a manifestement droit, par contre, concernant Nanard et Gillou, il y a ambiguïté : y ont-ils droit ? Ignore-t-on le montant de la prime ?)

    Il est évident que ceux qui font les SGBDR sont vigilants concernant le comportement des opérations dans lesquelles des valeurs nulles sont impliquées. Par exemple, si l’on augmente tout le monde de 200 euros, les salaires à null ne seront pas pris en compte et le système reste cohérent :

    Update Emp Set Salaire = Salaire + 200 ;

    =>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        id	 Pseudo   Salaire   Prime
        e1	 Jeannot   2200      200
        e2	 Sergio    1700      300
        e3	 Gillou	   1700     null
        e4	 Nanou	   null      200
        e5	 Riton	   null        0 
        e6	 Nanard	   1200     null 
    
                  Figure 2
    En contrepartie, on perd une certaine uniformité dans le comportement des opérations.
    Si aucun salaire n’est null, Avg (Salaire) est égal à Sum (Salaire) / Count (*), ce qui n’est pas le cas lorsque des salaires peuvent être à null, comme ci-dessus.

    Les requêtes méritent certains aménagements. En effet, par respect de la règle A+NULL = NULL, la requête ci-dessous produit un résultat néfaste concernant la fiche de paie de certains (table de référence : Figure 1) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Select Id, Pseudo, Salaire + Prime as 'Salaire + Prime'  From Emp ;
    =>
        id	 Pseudo   Salaire + Prime
        e1	 Jeannot        2200
        e2	 Sergio         1800
        e3	 Gillou	        null
        e4	 Nanou	        null
        e5	 Riton	        null 
        e6	 Nanard	        null
    Évidemment, il faudra retravailler sérieusement la requête.

    Je prends maintenant un exemple fourni par Chris Date, tiré de "Relational Database, Writings 1991 - 1994".

    Supposons qu’il existe une table Dpt des départements en relation avec la table Emp et que la situation soit la suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        Dpt  DptId    Nom    Budget
               d2     Prod   80000
    
        Emp  id      Pseudo   Salaire   DptId
             e1      Jeannot   2000      null
    On ne sait pas à quel département e1 est rattaché. Considérons la requête :

    ____Select EmpId
    ____From Dpt, Emp
    ____Where Not (Emp.DptId = Dpt.DptId And Emp.DptId = 'd1') ;

    Le résultat est vide.

    Appelons EXP1 l’expression " Emp.DptId = Dpt.DptId And Emp.DptId = 'd1' ".
    Situons-nous maintenant dans le monde réel : concernant d1, soit e1 en fait partie soit ce n’est pas le cas. Supposons qu’il en fasse partie. L’expression EXP1 a pour valeur de vérité celle du terme Emp.DptId=Dpt.DptId ("d1"="d2") c’est-à-dire faux.
    Supposons au contraire que e1 ne fasse pas partie de d1. L’expression EXP1 a pour valeur de vérité celle du terme Emp.DptId='d1' (¬"d1"="d1") c’est-à-dire faux.
    Dans le monde réel, la valeur de vérité de l’expression EXP1 est donc faux, peu importe ce que null représente exactement. A son tour, le sens de l’expression Not (EXP1) est vrai dans le monde réel et donc le résultat de la requête n’est pas vide mais "e1". SQL confirme, il suffit d’exécuter la requête pour s’en assurer, en affectant successivement à DptId la valeur "d1" ou "d2" dans la table Emp.

    Voilà quelques réflexions concernant la partie visible de l’iceberg.

    Le plus gros se trouve immergé, au sein du moteur relationnel du SGBD qui applique les lois de transformation pour l’optimisation des requêtes et peut se planter avec la logique ternaire. Ainsi, "p OR NOT p" est toujours vrai en logique binaire, mais pas en logique ternaire (null OR NOT null est null). De la même façon, x = x n’est pas toujours vrai dans cette logique, pas plus que x > y et y > z => x > z, pas plus que T JOIN T = T, T INTERSECT U = Y JOIN U, etc. Évidemment, sur notre banquise nous n'en avons guère conscience et cela peut nous laisser indifférents, mais ces identités reposent dans le cœur des moteurs relationnels... Si les identités ne fonctionnent pas, les lois de transformation sont prises en défaut et les accidents, les erreurs peuvent parfois se produire, d'où suspicion...

    Le sujet "Valeurs nulles" n'est ni anodin ni simple et a fait l’objet de débats dramatiques (cf. C.J. Date, "Relational Database, Writings 1994 - 1997"). Comme tout le monde j'ai usé et abusé de ces valeurs nulles, puis j'ai cherché à les éviter le plus possible. Je ne prétends pas pour ma part avoir résolu tous les problèmes, loin s’en faut, à tout le moins j'essaie de sensibiliser. A chacun de se réfléchir aux conséquences d'une consommation immodérée et irréfléchie. Comme je l'ai déjà dit, c'est de la dynamite et tout le monde n'est pas artificier...
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  10. #10
    Expert éminent sénior

    Avatar de Tofalu
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Octobre 2004
    Messages
    9 501
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Octobre 2004
    Messages : 9 501
    Points : 32 311
    Points
    32 311
    Par défaut
    Quel débat intéressant


    Les requêtes méritent certains aménagements. En effet, par respect de la règle A+NULL = NULL, la requête ci-dessous produit un résultat néfaste concernant la fiche de paie de certains (table de référence : Figure 1) :

    Là a vrai dire je ne suis pas d'accord. (enfin je pense)

    Pour moi le résultat donné par SQL correspond au monde réél :

    Si je ne connais pas le salaire de e4 (null), je suis incapable de lui ajouter quelque chose. Si je veux vraiment lui établir une fiche de paie, alors il me faut connaitre son salaire (0 par exemple). Cela doit être une saisie utilisateur. En aucun cas je ne peut prendre le risque d'aménager la requête de telle sorte quelle me remplace NULL par 0 et ainsi affirmer que e4 touchera 200 € alors que son véritable salaire est peut être de 2000 €.

    Vous proposez la table Visiteur (Id, Pseudo, Salaire), pour laquelle le salaire n’est pas nécessairement renseigné, par exemple parce qu’on ne le connaît pas encore (mais ça viendra plus tard), ou bien parce pour la personne, la notion de salaire ne s’applique pas, ou bien parce qu’elle refuse de le préciser, ou que sais-je encore. Pour tous ces cas de figure, on est conduit à utiliser la valeur nulle, laquelle sert pour tous ces cas de figure (ce qui n’est pas forcément satisfaisant).
    Quelle est selon vous, pour cet exemple, la modélisation "idéale" qui me permettrait de définir tous ces cas ?

    Pour les données de type chaînes de caractères, on peut l’éviter, avec par exemple une valeur par défaut à SPACE
    Remplacer une absence de valeur par une valeur jojer ne serait pas quelque part une dénormalisation, et ce tant au niveau logique que réel ? D'autre part, cela peut amener des pièges au niveau des concaténations par exemple.

    Si aucun salaire n’est null, Avg (Salaire) est égal à Sum (Salaire) / Count (*), ce qui n’est pas le cas lorsque des salaires peuvent être à null, comme ci-dessus.
    Je suis d'accord mais cela répond à deux problématiques différentes :

    Est ce que je veux connaitre la moyenne des salaires réellement distribués ou bien la moyenne du salaire pour tous les employés. Là, je comprend votre image de l'artificier. Evidemment, lorsque l'on sait que les NULL sont écartés par les fonctions d'aggrégats, on sait comment les aborder dans les calculs

    D'un point de vue théorique, on a toujours enseigné qu'une relation 0/1 d'un MCD se traduisait par une clé étrangère nullable au niveau du modèle relationnel. Si cette hypothése ne vous convient pas, pouvez vous me guider vers une démarche plus propre à vos yeux notamment sur l'exemple des salaires ?

  11. #11
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 760
    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 760
    Points : 52 541
    Points
    52 541
    Billets dans le blog
    5
    Par défaut
    Soit l'on modélise pour la théorie, donc il faut respecter ceci :
    http://web.onetel.com/~hughdarwen/Th...hout-nulls.pdf
    En l'occurrence aucune table ne devrait avoir plus d'une seule colonne en sus de la clef primaire.... Mais alors, bonjour les jontures !

    Soit l'on fait de la pratique et alors il faut accepter la fatalité des NULLs.

    Dans l'exemple de fsmrel, rajoutons à la table la colonne DATE_NAISSANCE. Si l'on veut à tout prix et de manière imbécile éviter les NULL et que l'on ne connait pas la date de naissance de certains employés, il faudra mettre une date de naissance bidon, qui induira immanquablement :
    soit à des erreurs de calculs (exemple âge moyen des salariés si date bidon = 1/1/1900)
    soit à des requêtes plus complexes pour oter les dates bidons.
    Exemple :
    SELECT AVG(DATE_NAISS)
    FROM T_EMPLOYEE
    WHERE DATE_NAISS <> 01/01/1900

    Et comme on le voit cette dernière requête comporte un prédicat non "seargable" donc un plan d'exécution catastrophique !

    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/ * * * * *

  12. #12
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 001
    Points : 30 905
    Points
    30 905
    Billets dans le blog
    16
    Par défaut
    Bonjour,

    Citation Envoyé par Tofalu
    Fsmrel a écrit :
    Les requêtes méritent certains aménagements. En effet, par respect de la règle A+NULL = NULL, la requête ci-dessous produit un résultat néfaste concernant la fiche de paie de certains (table de référence : Figure 1)
    Point sur lequel Tofalu pense ne pas être d’accord :
    Citation Envoyé par Tofalu
    Là a vrai dire je ne suis pas d'accord. (enfin je pense)
    J’espère qu’il n’y a pas de confusion ! Quand j’évoque un résultat néfaste, il faut interpréter cela vu du salarié, car il ne touchera pas un kopek. En logique trivalente, le résultat NULL est valide, nous n’y pouvons rien...


    Citation Envoyé par Tofalu
    Pour moi le résultat donné par SQL correspond au monde réél :
    Si je ne connais pas le salaire de e4 (null), je suis incapable de lui ajouter quelque chose. Si je veux vraiment lui établir une fiche de paie, alors il me faut connaitre son salaire (0 par exemple). Cela doit être une saisie utilisateur. En aucun cas je ne peux prendre le risque d'aménager la requête de telle sorte quelle me remplace NULL par 0 et ainsi affirmer que e4 touchera 200 € alors que son véritable salaire est peut être de 2000 €.
    Dans le monde réel, quand vous avez à remplir un formulaire administratif et qu’une rubrique ne vous concerne pas, vous y inscrivez "sans objet" ou "?" ou bien encore vous biffez d’un trait, vous laissez à blanc, etc., toute marque au fond synonyme de valeur par défaut et que la personne chargée de saisir l’information interprétera tacitement comme telle. Cette personne et vous-même avez raisonné selon une logique binaire : dans le monde réel, il n’y a rien qui corresponde à NULL. C’est à vous de prendre les dispositions qui fassent que SQL donne des résultats qui correspondent au monde réel. SQL utilise NULL et s’appuie sur une logique trivalente ("vrai", "faux", "inconnu") pour traiter le problème de l’absence d’information. Nous n’y pouvons rien, il est ainsi bâti.

    Par exemple, quand on écrit :

    Select Id
    From Emp
    Where Pseudo = "Tofalu" Or Not Pseudo = "Tofalu" ;

    Dans le monde réel il est clair que l’on récupère tout le monde. De son côté, si certains pseudos sont à null, SQL ne vous fournira que le sous-ensemble des pseudos qui ne sont pas à null : en l’occurrence, SQL ne fournit pas les mêmes informations que celles que l’on obtient dans le monde réel.

    A cette occasion je reprends que j’ai écrit précédemment :
    Cet inconnu (unknown) est encore appelé NULL
    Je précise que NULL et unknown ne sont pas la même chose. Je vous renvoie à ce sujet aux ouvrages de Chris Date.

    Pour l’anecdote, je cite les frères Jolivet (dans les années soixante-dix) :

    « 40% des gens ont un chat, 30% un chien et 30% n’ont pas d’opinion ».


    Citation Envoyé par Tofalu
    La morale (qui peut être ici assimilée à une contrainte de gestion) me force à donner le choix à mes visiteurs de renseigner leur salaire ou pas. Je ne peux donc pas interdire les valeurs nulles pour le salaire.
    Comme je l’ai déjà précisé, il est plus sain de définir une table pour les salaires. Incidemment, cela permet de protéger l’accès à ces données particulièrement sensibles (que ce soit en consultation ou en mise à jour). Et tant que nous y sommes, faisons-en autant pour les primes...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    					
        Emp                              Salaire                      Prime
        Id    Pseudo   IndPrime          Id    Salaire                Id    Prime
        e1    Jeannot     V              e1      2000                 e1     200
        e2    Sergio      V              e2      1500                 e2     300
        e3    Gillou      F              e3      1500                 e4     200
        e4    Nanou       V              e6      1000                 e5       0
        e5    Riton       V
        e6    Nanard      V
                                       Figure 4
    La table Emp a été débarrassée des attributs Salaire et Prime, désormais respectivement transférés dans les nouvelles tables Salaire et Prime. En contrepartie, la table Emp est dotée d’un nouvel attribut IndPrime, grâce auquel on peut signaler si un employé fait partie ou non de ceux qui ont droit à une prime ("V" pour ceux qui ont droit, "F" dans le cas contraire). Par hypothèse, tout le monde ayant un salaire, si e4 et e5 sont absents de la table Salaire, c’est que leur salaire est inconnu. Si on veut en savoir plus, on peut toujours ajouter un attribut MotifAbsenceSalaire à la table Emp, donnant la raison de cette absence. Si les gens peuvent avoir plusieurs primes, rien n’empêche de rajouter un attribut TypeDePrime pour la table Prime et de prévoir dans Emp autant d’indicateurs que de types de primes (sans oublier de compléter la clé primaire de Prime par un attribut de type séquenceur relatif). Etc., etc.


    Citation Envoyé par Tofalu
    Remplacer une absence de valeur par une valeur jojer ne serait pas quelque part une dénormalisation, et ce tant au niveau logique que réel ? D'autre part, cela peut amener des pièges au niveau des concaténations par exemple.
    La dénormalisation est autre chose : il s’agit de remplacer deux tables T1 et T2 par leur jointure T (en sorte que par projection, on puisse retrouver T1 et T2). Maintenant, l’utilisation d’une valeur joker est légale, dans la mesure où cette valeur fait partie du domaine de référence de l’attribut concerné. Ainsi, tout nombre entier peut servir de valeur par défaut si le domaine de référence d’un attribut est celui des entiers. En contrepartie, NULL ne fait pas partie des entiers. Maintenant, si aucun entier ne peut servir comme valeur par défaut pour les salaires, autant mettre en œuvre la table Salaire (ou utiliser la valeur nulle pour ceux qui sont artificiers ou qui n’ont pas froid aux yeux, mais risquent de ficher leurs successeurs dans la patouille quand ils auront été exercé leurs talents sous d’autres cieux : j’ai observé cela !)
    Concernant la concaténation, il est un fait que X || Y est NULL si X ou Y est null, alors que X || ' ' ne l’est pas si X ne l’est pas. Je n’ai pas trop réfléchi à cette alternative, donc m’abstiendrai de donner un avis. Si vous connaissez des exemples de pièges, je suis preneur...


    Citation Envoyé par Tofalu
    D'un point de vue théorique, on a toujours enseigné qu'une relation 0/1 d'un MCD se traduisait par une clé étrangère nullable au niveau du modèle relationnel. Si cette hypothése ne vous convient pas, pouvez vous me guider vers une démarche plus propre à vos yeux notamment sur l'exemple des salaires ?
    Il est vrai que beaucoup ont enseigné qu'une relation 0/1 d'un MCD se traduisait par une clé étrangère pouvant être nulle au niveau relationnel, mais sans avoir conscience des conséquences. Cela dit, l’approche entité/relation en général et Merise en particulier ne sont pas des théories. Merise est une « Méthode de définition d’un Système d’Informations ». Vu mon peu d’attrait pour les valeurs nulles, autant vous dire qu’au niveau conceptuel je tiens à ne jamais produire de MCD dans lequel on aurait des cardinalités 0,N-0,1 ou 0,1-0,1. D’autant plus qu’en l’occurrence, de telles cardinalités sont généralement un signe que le MCD n’a pas été suffisamment "déplié". Si donc je vois que dans un MCD, les entités-types X et Y sont liées par une relation-type R avec ce genre de cardinalités, je transforme le système :

    De X----0,N--R--0,1----Y

    je passe à

    X----0,N--R1--1,1----R--(1,1)--R2--0,1----Y

    R étant devenu une entité-type associative et R1, R2 de nouvelles relations-types (la cardinalité entre parenthèses (1,1) signifie que R est identifiée relativement à Y).

    Au niveau relationnel, cela donne :

    X (Xid, ...Primary Key (Xid))
    Y (Yid, ...Primary Key (Yid))
    R (Yid, Xid, ..., Primary Key (Yid), Foreign Key (Xid) References X, Foreign Key (Yid) References Y))

    Et les attributs Xid et Yid sont systématiquement déclarés Not Null.

    Cardinalités 0,1-0,1 : même principe.

    Ceci permet aussi de résoudre certains problèmes d’enneigement (quelques valeurs de clés étrangères non nulles au milieu d’un amoncellement de valeurs nulles au sein de Y : cela ne fait pas sérieux, surtout quand le phénomène est amplifié dès lors que cette situation se reproduit à qui mieux mieux).

    Clés étrangères partiellement nulles

    Notez en passant que si une clé étrangère est composée de plusieurs attributs dont au moins l’un d’entre eux prend la valeur nulle, alors le système considère que la clé étrangère elle-même est nulle : il n’y a donc aucun contrôle concernant les autres attributs et l’on peut y fourrer tout et n’importe quoi, d’où possibilité de soumettre des requêtes fournissant des résultats à la mesure (c’est le GIGO des anglo-saxons).


    Citation Envoyé par SQLpro
    Soit l'on modélise pour la théorie, donc il faut respecter ceci :
    http://web.onetel.com/~hughdarwen/Th...hout-nulls.pdf
    En l'occurrence aucune table ne devrait avoir plus d'une seule colonne en sus de la clef primaire.... Mais alors, bonjour les jontures !
    Soit l'on fait de la pratique et alors il faut accepter la fatalité des NULLs.
    Justement ! En tant que praticien, je commence par modéliser en pensant notamment aux valeurs nulles. Au niveau relationnel, j’en arriverai à avoir plus de tables, mais sans valeurs nulles, comme dans le cas de la figure 4 ci-dessus (la base de données comporte 2000 tables ? J’y ai eu affaire...) Par ailleurs, je n’ai aucune émotion face au nombre de tables participant à une requête. Maintenant, il est évident que je prototype tant et plus, afin de vérifier les temps de réponse des transactions, la durée des traitements de type batch, quelles que soient les requêtes. Je vérifie aussi la charge CPU, surveille si ces jointures ne conduisent pas à des phénomènes d’I/O bound (ralentissement très sensible, pour attente de fin des entrées/sorties). Après 20 ans de baroud avec DB2, j’ai tiré un certain nombre d’enseignements ès matière. Si le verdict du prototype fait que je suis contraint à faire une table à partir d'autres tables, je le fais : comme vous dites, il m’arrive d’accepter la fatalité des NULL. Mais je ne fais rien sous le coup d’une émotion compréhensible, causée par des requêtes où l’on trouverait 10 jointures impliquant des tables comportant des dizaines de millions de lignes. Pour reprendre l’exemple de la figure 4, s’il le faut, les tables seront hébergées par des table spaces partitionnés (au sens DB2 du terme), et indexées par des index de type cluster (toujours au sens DB2 du terme) sur la clé primaire et je sais quand même que le phénomène d’I/O bound aura très peu de chances de se produire et que la CPU ne se tournera pas les pouces.

    Citation Envoyé par SQLpro
    Si l'on veut à tout prix et de manière imbécile éviter les NULL
    Il serait plus à propos d’écrire : « Si l’on veut éviter les NULL, du mieux possible et de manière intelligente »... C’est moins chargé d’émotion et c’est plus constructif, surtout pour les plus jeunes qui lisent tout ceci.

    Citation Envoyé par SQLpro
    SELECT AVG(DATE_NAISS)
    FROM T_EMPLOYEE
    WHERE DATE_NAISS <> 01/01/1900
    Et comme on le voit cette dernière requête comporte un prédicat non "seargable" donc un plan d'exécution catastrophique !
    Je ne pense pas que la requête aille beaucoup plus vite sans la clause WHERE. Dans les deux cas en effet, il y aura un "table scan" (balayage de la table) ou au mieux un "non matching index scan" (balayage des feuilles de l’index, si la table est indexée et que l’index est un arbre B+). Pour mémoire, avec DB2 le prédicat DATE_NAISS <> 01/01/1900 est sargable.
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  13. #13
    Membre expert
    Homme Profil pro
    Retraité
    Inscrit en
    Octobre 2005
    Messages
    1 473
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Finance

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 473
    Points : 3 283
    Points
    3 283
    Par défaut
    Citation Envoyé par fsmrel
    ... Pour mémoire, avec DB2 le prédicat DATE_NAISS <> 01/01/1900 est sargable.
    Je confirme ...
    Avec DB2 for z/OS V7, ce prédicat est dit de "stage 1" (ou "sargable") mais, par contre, il est non indexable (ce qui est quand même pas terrible ...)
    Predicate types and processing (V7)

  14. #14
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 001
    Points : 30 905
    Points
    30 905
    Billets dans le blog
    16
    Par défaut
    Bonsoir,

    Citation Envoyé par Luc Orient
    Avec DB2 for z/OS V7, ce prédicat est dit de "stage 1" (ou "sargable") mais, par contre, il est non indexable (ce qui est quand même pas terrible ...)
    Certes Luc Orient, le prédicat DATE_NAISS <> 01/01/1900 n’est pas indexable, mais sa mission est seulement de faire dégager du résultat final les lignes pour lesquelles la date de naissance est égale au 01/01/1900 : il ne faut pas lui en demander plus !

    Du reste, si le prédicat provoquait l’élimination de 90% des lignes, je serais très inquiet quant à la qualité de la modélisation, car il ne faut pas oublier le rôle qui lui a été dévolu...

    Maintenant, on peut aussi coder : DATE_NAISS > 01/01/1900, théoriquement indexable, mais sans grand intérêt...
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

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

Discussions similaires

  1. BI entre la théorie et la pratique
    Par chagala dans le forum Contribuez
    Réponses: 0
    Dernier message: 01/03/2011, 23h39
  2. Réponses: 5
    Dernier message: 10/07/2010, 18h52
  3. connection internet division theorie et pratique
    Par CLion dans le forum Administration
    Réponses: 5
    Dernier message: 05/01/2010, 19h08
  4. Bonne pratique - données entre pages?
    Par fabszn dans le forum JSF
    Réponses: 6
    Dernier message: 03/10/2007, 13h17
  5. [Theorie] Passage des informations entre les redolog et les tbs undo
    Par lecharcutierdelinux dans le forum Administration
    Réponses: 10
    Dernier message: 07/06/2007, 09h11

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