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

Langage SQL Discussion :

Jointure qui fonctionne alors qu'elle ne le devrait pas


Sujet :

Langage SQL

  1. #1
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 717
    Points : 31 028
    Points
    31 028
    Billets dans le blog
    1
    Par défaut Jointure qui fonctionne alors qu'elle ne le devrait pas
    Bonjour à tous

    Donc oui, j'ai un souci de jointure car en essayant d'écrire un truc de test je suis arrivé à une jointure qui fonctionne alors qu'elle ne le devrait pas.

    Prenons 2 tables: produit et fournisseur. Vu qu'un produit peut être fourni par plusieurs fournisseurs, et qu'un fournisseur peut fournir plusieurs produits, on va rajouter une relation 'approvisionner" pour faire le lien.
    Ce qui donne le modèle suivant
    Nom : Sans titre.jpg
Affichages : 216
Taille : 22,5 Ko

    Voici les tables (bdd PostgreSQL)
    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
    -- Table "produit"
    drop table if exists "produit" cascade;
    create table "produit" (
    	"id_produit" smallint,
    	"nom" character varying(20),
    	"qte" smallint,
    	"tva" decimal(4, 2),
    	primary key ("id_produit")
    );
     
    -- Remplissage
    insert into "produit" values (1, 'dentifrice', 40, '20.0');
     
    -- Table "fournisseur"
    drop table if exists "fournisseur" cascade;
    create table "fournisseur" (
    	"id_fournisseur" smallint,
    	"nom" character varying(20),
    	"telephone" character(10),
    	primary key ("id_fournisseur")
    );
     
    -- Remplissage
    insert into "fournisseur" values (10, 'fournisseurA', '123456');
    insert into "fournisseur" values (20, 'fournisseurB', '654321');
    insert into "fournisseur" values (30, 'Autre', '999999');
     
    -- Table "approvisionner"
    drop table if exists "approvisionner" cascade;
    create table "approvisionner" (
    	"id_produit" smallint,
    	constraint "fk_produit" foreign key ("id_produit")
    		references "produit" ("id_produit") match full
    		on update cascade on delete cascade,
    	"id_fournisseur" smallint,
    	constraint "fk_fournisseur" foreign key ("id_fournisseur")
    		references "fournisseur" ("id_fournisseur") match full
    		on update cascade on delete restrict,
    	"prix_achat" decimal(7, 2) not null check ("prix_achat" > 0),
    	primary key ("id_produit", "id_fournisseur")
    );
     
    -- Remplissage
    insert into "approvisionner" values (1, 10, '2.20');
    insert into "approvisionner" values (1, 20, '2.17');

    De là, si on veut les fournisseurs de notre dentifrice, il faut faire deux jointures imbriquées. Pour l'instant pas de problème...
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    -- test jointure n° 1
    select produit.*, fournisseur.*
    from produit
    inner join approvisionner
    	inner join fournisseur on fournisseur.id_fournisseur = approvisionner.id_fournisseur
    on approvisionner.id_produit = produit.id_produit;

    Toutefois j'ai tenté la jointure suivante...
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    -- test jointure n° 2
    select produit.*, fournisseur.*
    from produit
    inner join approvisionner on approvisionner.id_produit = produit.id_produit
    inner join fournisseur on fournisseur.id_fournisseur = approvisionner.id_fournisseur;
    ...qui, surprise, m'a donné le même résultat. Pourtant, telle qu'elle est écrite, cette seconde jointure n'est pas imbriquée dans la première. Dans mon esprit elle n'aurait pas dû fonctionner. Ecrire ...from produit inner join fournisseur indique que produit est directement lié à fournisseur alors que ce n'est pas le cas.

    Ai-je loupé un truc sur les jointures ?

    Merci à tous de votre attention.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  2. #2
    Modérateur
    Avatar de sevyc64
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    10 206
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 206
    Points : 28 129
    Points
    28 129
    Par défaut
    Pour moi les deux formes d'écriture sont strictement identiques.

    Personnellement, je n'utilise jamais la forme "imbriquée" que je trouve extrêmement difficile à comprendre et à debugger lorsque tu commence à avoir de grosses requêtes avec parfois plus d'une 10ènes de jointures.
    D'ailleurs, je pense que certains SGBD ne doivent pas accepter cette forme d'écriture.
    C'était la forme qu'il fallait utiliser avec certains moteurs, typiquement les vieux Access (je n'utilise plus Access, ça n'a peut être pas changé) et c'était une véritable plaie pour peu que tu te ratais dans une des imbrications.


    Citation Envoyé par Sve@r Voir le message
    Ecrire ...from produit inner join fournisseur indique que produit est directement lié à fournisseur alors que ce n'est pas le cas.
    Non pas du tout.
    Ce qui fait réellement la jointure ce n'est pas le Join, mais bien la clause ON du join. Ici Fournisseur n'est en aucun cas lié à Produit puisqu tu précise justement que le lien se fait avec Approvisionner
    --- Sevyc64 ---

    Parce que le partage est notre force, la connaissance sera notre victoire

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 717
    Points : 31 028
    Points
    31 028
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par sevyc64 Voir le message
    Pour moi les deux formes d'écriture sont strictement identiques.
    Ok, donc ce que j'ai raté c'est juste le fait que l'écriture imbriquée n'est pas une obligation.

    Citation Envoyé par sevyc64 Voir le message
    Ce qui fait réellement la jointure ce n'est pas le Join, mais bien la clause ON du join
    Oui effectivement. Mais je voyais aussi ça comme une espèce d'empilement. On associe "produit" à "approvisionner" mais ce n'est pas fini, il faut ensuite aller sur "fournisseur". Et là seulement on a fini et on peut alors remonter la chaine via les "on". Bref le principe de l'imbriqué.
    Après ça doit être aussi une question d'habitude (ceci dit je ne suis jamais allé jusqu'à 10 jointures).

    Ok merci du retour
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 232
    Points : 12 846
    Points
    12 846
    Par défaut
    Bonjour,
    Pour ma part j'utilise les jointures imbriquées dans un cas seulement: pour "mixer" une jointure externe et une jointure interne.
    Par exemple:
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    select client.cli_c_nom,client.cli_c_prenom,facture.fac_t_saisie,ligne_facture.lf_f_quantite,article.art_c_uvc
    from client
    left outer join facture
        inner join ligne_facture
            on ligne_facture.fac_i_ident = facture.fac_i_ident
        inner join article 
            on article.art_i_ident = ligne_facture.art_i_ident
        on facture.cli_i_ident = client.cli_i_ident
    where ...
    Ici je veux tous les clients, et leurs éventuelles factures avec quelques infos sur les lignes et les articles de ces factures.

    Tatayo.

  5. #5
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 266
    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 266
    Points : 39 407
    Points
    39 407
    Billets dans le blog
    9
    Par défaut
    Bonjour,

    Citation Envoyé par Sve@r Voir le message
    Ok, donc ce que j'ai raté c'est juste le fait que l'écriture imbriquée n'est pas une obligation.
    Cette syntaxe est impérative si l'on combine des jointures internes et externes, c'est un piège classique dans lequel tombent beaucoup de développeurs peu expérimentés.
    C'est la raison pour laquelle j'ai consacré un billet de blog à ce sujet ICI

    Mais ici, nous avons affaire à deux jointures internes, ce faisant, la syntaxe est libre.

    Par ailleurs, mettre une colonne "TVA" dans la table des produits, qu'il s'agisse du taux ou du montant, est une erreur de modélisation :
    le taux de TVA change régulièrement sur décision gouvernementale, il faut donc le stocker dans une table dédiée (identifiant, code, taux, date de début de validité, date de fin de validité) et établir un lien d'association entre le produit et le taux.
    Ainsi, si le taux change, une à deux lignes seulement seront impactées dans cette table, alors qu'avec le taux stocké dans les produits, il faudra mettre à jour en masse toute la table

  6. #6
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 266
    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 266
    Points : 39 407
    Points
    39 407
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par sevyc64 Voir le message
    Pour moi les deux formes d'écriture sont strictement identiques.

    Personnellement, je n'utilise jamais la forme "imbriquée" que je trouve extrêmement difficile à comprendre et à debugger lorsque tu commence à avoir de grosses requêtes avec parfois plus d'une 10ènes de jointures.
    D'ailleurs, je pense que certains SGBD ne doivent pas accepter cette forme d'écriture.
    C'était la forme qu'il fallait utiliser avec certains moteurs, typiquement les vieux Access (je n'utilise plus Access, ça n'a peut être pas changé) et c'était une véritable plaie pour peu que tu te ratais dans une des imbrications.
    Absolument pas, comme je l'explique plus haut, c'est une syntaxe impérative quand on combine des jointures INNER et OUTER ! Voir mon blog à ce sujet
    Fort heureusement, tous les SGBD acceptent cette syntaxe à part SQLite semble-t-il, mais ce SGBD présente bien d'autres défauts

  7. #7
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 717
    Points : 31 028
    Points
    31 028
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par escartefigue Voir le message
    Par ailleurs, mettre une colonne "TVA" dans la table des produits, qu'il s'agisse du taux ou du montant, est une erreur de modélisation :
    Ca dépend du degré d'importance que cette donnée aura dans le système. Toutefois il se trouve que ceci fait partie d'un TP dans lequel justement je montre comment et pourquoi déporter la TVA
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  8. #8
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    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 453
    Points : 18 383
    Points
    18 383
    Par défaut
    Citation Envoyé par escartefigue Voir le message
    Cette syntaxe est impérative si l'on combine des jointures internes et externes, c'est un piège classique dans lequel tombent beaucoup de développeurs peu expérimentés.
    95% (source doigt mouille) des requetes melangeant inner et outer join sont comme ca
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
          from t1
    inner join t2 on t2.col1 = t1.col1
     left join t3 on t3.col2 = t2.col2
     left join t4 on t4.col2 = t2.col2
    inner join t5 on t5.col3 = t1.col3
    Et l'imbrication n'a ici aucun interet.

    Celle soulevee par tatayo me parait la seule valable, et si on veut etre ceinture et bretelle on rajoute des parentheses :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    from client
    left outer join ( facture
        inner join ligne_facture
            on ligne_facture.fac_i_ident = facture.fac_i_ident
        inner join article 
            on article.art_i_ident = ligne_facture.art_i_ident )
        on facture.cli_i_ident = client.cli_i_ident

  9. #9
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 266
    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 266
    Points : 39 407
    Points
    39 407
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Ca dépend du degré d'importance que cette donnée aura dans le système. Toutefois il se trouve que ceci fait partie d'un TP dans lequel justement je montre comment et pourquoi déporter la TVA
    Non : d'une part parce que toute donnée du SGBD se doit d'être fiable, sinon elle n'a pas d'intérêt, d'autre part parce que si la TVA est portée sur chaque article, lorsque la réglementation change, il faut modifier toutes les lignes de la table article portant ce taux de TVA.



    Citation Envoyé par Waldar Voir le message
    95% (source doigt mouille) des requetes melangeant inner et outer join sont comme ca
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
          from t1
    inner join t2 on t2.col1 = t1.col1
     left join t3 on t3.col2 = t2.col2
     left join t4 on t4.col2 = t2.col2
    inner join t5 on t5.col3 = t1.col3
    Et l'imbrication n'a ici aucun interet.
    Evidemment, car dans cet exemple, T5 fait une jointure interne avec la table T1...
    Le cas dont il est question est quand la table T5 fait l'objet d'une jointure interne avec l'une des tables en jointure externe
    par exemple left join t2 on t2.col2 = t1.col2 inner join t5 on t5.col3 = t2.col3.
    Et là, on peut mettre toutes les parenthèses qu'on veut, ça ne change rien à l'affaire !

    Il suffit de copier coller l'exemple donné dans mon blog dans n'importe quel interpréteur SQL pour le vérifier

  10. #10
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 717
    Points : 31 028
    Points
    31 028
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par escartefigue Voir le message
    Et là, on peut mettre toutes les parenthèses qu'on veut, ça ne change rien à l'affaire !
    Donc autant rester tout le temps en jointures imbriquées pour être certain de ne jamais tomber dans un cas foireux non ?
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  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 837
    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 837
    Points : 52 927
    Points
    52 927
    Billets dans le blog
    5
    Par défaut
    Pourquoi faire simple quand on peut faire compliqué ?

    De plus avec des mélange INNER/OUTER JOIN cela ne donnera pas le même résultat...

    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 Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 717
    Points : 31 028
    Points
    31 028
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par SQLpro Voir le message
    Pourquoi faire simple quand on peut faire compliqué ?
    Alors déjà quand on n'a pas été élevé chez les sangliers on apprend qu'il est très malpoli de répondre à une question par une question.
    Ensuite iles raisons qui peuvent orienter la décision sont incluses avec la question du post précédent et c'était sur ces raisons que j'espérais une discussion réfléchie et argumentée. Donc puisqu'il faut qu'on te mette les point sur les "i" hé bien parce que visiblement il existe des cas où la simplicité ne donne pas le résultat attendu (et j'ai testé les exemples de escartefigue et effectivement ça arrive)... tandis que la jointure imbriquée, même si elle te semble complexe, aura au-moins l'avantage de ne pas avoir cet inconvénient.

    Citation Envoyé par SQLpro Voir le message
    De plus avec des mélange INNER/OUTER JOIN cela ne donnera pas le même résultat...
    Certes mais ce n'est pas le sujet ici. Toujours à ramener ton grain de sel sans prendre la peine de lire ce que les autres ont écrit quoi.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  13. #13
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 837
    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 837
    Points : 52 927
    Points
    52 927
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    ... parce que visiblement il existe des cas où la simplicité ne donne pas le résultat attendu (et j'ai testé les exemples de escartefigue et effectivement ça arrive)... tandis que la jointure imbriquée, même si elle te semble complexe, aura au-moins l'avantage de ne pas avoir cet inconvénient.
    Contrairement à ce que vous pensez le problème est solvable sans utiliser différents types de jointures...

    Je montre d'ailleurs un exemple dans le livre sur SQL que j'écris en ce moment dans le chapitre 5 consacré aux jointures. Voici le modèle :

    Nom : 5.1 - MCD LOGISTYX personnes power Designer.jpg
Affichages : 87
Taille : 647,4 Ko

    Voici le cas de figure

    Nom : Jointure commutativité.jpg
Affichages : 86
Taille : 1,00 Mo

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

  14. #14
    Membre expérimenté
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Septembre 2016
    Messages
    766
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2016
    Messages : 766
    Points : 1 473
    Points
    1 473
    Par défaut
    Citation Envoyé par escartefigue Voir le message
    Par ailleurs, mettre une colonne "TVA" dans la table des produits, qu'il s'agisse du taux ou du montant, est une erreur de modélisation :
    le taux de TVA change régulièrement sur décision gouvernementale, il faut donc le stocker dans une table dédiée (identifiant, code, taux, date de début de validité, date de fin de validité) et établir un lien d'association entre le produit et le taux.
    Ainsi, si le taux change, une à deux lignes seulement seront impactées dans cette table, alors qu'avec le taux stocké dans les produits, il faudra mettre à jour en masse toute la table
    Nous sommes totalement d'accord que garder le "montant" de TVA dans la table produits est une erreur.

    Pour le reste, je serais plus modéré :

    Avoir une table des taux de TVA est très utile pour "remplir" les listes déroulantes.
    De là a ce qu'elle serve aussi de contrainte d'intégrité, je ne suis pas certain.

    Selon mon expérience, les modifications de taux (purement le taux) est bien moins fréquent que les changements d'affectation de TVA (TVA à taux réduit, ...)
    Donc stoker l'historique des changements des taux d'un même code ne me semble pas être une imposition forte.
    Les mise à jour de l'ID de TVA (ou directement du code) représentant le même effort vu que c'est pratiquement ligne par ligne que c'est décidé.
    Exemple : un kit de jeu de rôle sera considéré comme un jeux (tva standard) ou comme un livre (tva réduite) en fonction de ... l'administration du moment.

    Pour moi la sémantique associée à la colonne "TVA" dans la table produit est : taux de TVA applicable par défaut.
    Faudrait pas oublier les différentes conditions de ventes, et notamment les "free tax" qui influent sur la TVA à appliquer.
    La/les règle(s) de gestion de la TVA sont telles qu'on puisse les considérer comme trop lourdes à modéliser et à suivre au quotidien.
    Autant ne pas contraindre sa saisie.

    Dans tous les cas, la table des "lignes de facture" a tout intérêt à avoir une colonne TVA dont la sémantique est : TVA appliquée à cet élément vendu, dans le contexte de la facture courante.
    Le savoir est une nourriture qui exige des efforts.

  15. #15
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 717
    Points : 31 028
    Points
    31 028
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par SQLpro Voir le message
    Contrairement à ce que vous pensez
    Que sais-tu de ce que je pense ? Visiblement pas grand chose vu que tu ne fais même pas l'effort de lire ce que j'écris pour redire au final exactement la même chose !!!

    Citation Envoyé par SQLpro Voir le message
    le problème est solvable
    Je n'ai pas posé de problème, j'ai juste posé une question sur deux façons d'écrire une requête dont l'une me semble incorrecte tout en donnant quand-même un résultat cohérent. Mais pour moi il n'y a aucun problème si on passe par l'écriture puriste des jointures imbriquées pour suivre la "logique" du modèle. Et les réponses des autres intervenants (qui montrent qu'effectivement l'écriture incorrecte amènera à plus ou moins long terme des résultats incorrects) m'ont conforté dans cette façon de voir.
    Et pour info, "solvable" désigne une personne qui a les moyens de payer. Pour indiquer la possibilité d'un problème d'être résolu l'adjectif est "résoluble".

    Citation Envoyé par SQLpro Voir le message
    sans utiliser différents types de jointures...
    Je ne sais même pas ce que tu entends par "type". Parles-tu de jointures inner/outer ? En tout cas moi je n'ai jamais évoqué un quelconque souci à leur sujet.

    Citation Envoyé par SQLpro Voir le message
    Je montre d'ailleurs un exemple dans le livre sur SQL que j'écris en ce moment dans le chapitre 5 consacré aux jointures.
    On remarquera donc que tu utilises au final (dans ta dernière requête) bel et bien les jointures imbriquées, ce qui était aussi ma suggestion à laquelle tu as répondu ton aussi inélégant que déplacé "pourquoi faire simple...". Bref toujours aussi fantoche quoi.
    Accessoirement, pour tes deux premières requêtes, je ne vois pas pourquoi tu tabules la seconde jointure interne (le second "left outer join") pour la décaler de la première alors qu'elles ne sont justement pas imbriquées. Tabuler les jointures dans l'écriture ne les imbrique pas pour autant. D'ailleurs je ne vois même pas pourquoi on irait les écrire ces deux premières requêtes. Dans le modèle on voit bien que "t_personne_physique_psp" va sur "t_telephone_tel" qui lui part sur "t_r_telephone_type_ttl" ; ce chainage en 2 étapes entraîne directement des jointures imbriquées de la 3° requête (et on en revient donc de nouveau à ma dernière suggestion).
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  16. #16
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 266
    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 266
    Points : 39 407
    Points
    39 407
    Billets dans le blog
    9
    Par défaut
    Bonjour Michel

    Cette discussion est un peu en marge du sujet, les participants nous pardonneront, je l'espère, cette digression.


    Citation Envoyé par Michel.Priori Voir le message
    Selon mon expérience, les modifications de taux (purement le taux) est bien moins fréquent que les changements d'affectation de TVA (TVA à taux réduit, ...)
    Sans doute est-ce parce que je me fais vieux que je me souviens de nombreux changements de taux et de tranches de TVA : quand j'étais jeune, les disques, la hifi et autres produits dits "de luxe" étaient taxés à 33% et il y avait 4 taux en vigueur !
    Ça a changé bien des fois, on peut en retrouver l'historique ICI



    Citation Envoyé par Michel.Priori Voir le message
    Faudrait pas oublier les différentes conditions de ventes, et notamment les "free tax" qui influent sur la TVA à appliquer.
    Ce n'est pas parce que certaines prestations ou certains clients sont exonérés de TVA que ça impacte la façon de stocker les taux en table pour les cas d'assujettissement.

  17. #17
    Membre expérimenté
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Septembre 2016
    Messages
    766
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2016
    Messages : 766
    Points : 1 473
    Points
    1 473
    Par défaut
    Citation Envoyé par escartefigue Voir le message
    Sans doute est-ce parce que je me fais vieux que je me souviens de nombreux changements de taux et de tranches de TVA : quand j'étais jeune, les disques, la hifi et autres produits dits "de luxe" étaient taxés à 33% et il y avait 4 taux en vigueur !
    Ça a changé bien des fois, on peut en retrouver l'historique ICI

    Ce n'est pas parce que certaines prestations ou certains clients sont exonérés de TVA que ça impacte la façon de stocker les taux en table pour les cas d'assujettissement.
    Merci Escartefigue de ta réponse, loin de la polémique, documentée fort à propos et amenant de l'eau au moulin. Merci.

    Reprenons donc nos remarques sur la modélisation du taux de TVA
    Nous sommes tout 2 convaincus qu'il faille une table de "taux de TVA".
    Cependant nos points de vue divergent sur sa structure et sur les "relations".

    Citation Envoyé par escartefigue Voir le message
    il faut donc le stocker dans une table dédiée (identifiant, code, taux, date de début de validité, date de fin de validité) et établir un lien d'association entre le produit et le taux
    Une telle table revient à stoker l'historique des changements des taux.
    Cette modélisation s'avèrera utile lors du prochain changement car on pourra saisir "à l'avance" les futurs taux applicables.

    En optant pour cette logique, alors, l'intégrité référentielle avec la table produits n'est pas de mise.
    Faut une table intermédiaire. On ne peut pas être directement lié à la table produits.
    Les règles d'allocation du type de taux de TVA pour chaque produit change tout autant que le taux lui même.
    Les création/suppression des types de taux (super réduit, intermédiaire, majoré, ...) forcent la réallocation du type pour chaque produit (et à la mano car on à 99% de chance de ne pas avoir stocké le critère d'attribution en tant qu'attribut du produit).
    Si on veux être cohérent avec l'historisation du taux de TVA il faut aussi faire la même chose pour le type de taux, produit par produit.
    Ainsi on pourra tout autant pré-saisir la modification du type de taux dont relève le kit JDR (jeux ou littérature ?) en fonction des parutions officielles, que les changements de taux eux mêmes.

    Pour moi, cela relève "du monde de mickey".
    D'une part les acteurs économiques rechignent à dépenser de l'énergie pour un sujet qui n'est pas leur cœur de métier (Cf les fiches de paie).
    C'est la raison principale pour que la pré saisie, qui nécessite une actualisation régulière de l'information, ne soit pas ou peu faite.
    D'autre part, la majorité des acteurs économiques ont une game de produits qui ne relèvent de l'ensemble de la palette de taux de TVA.
    Leur activité principale relève du code NAF, signe qu'elle est ciblée.
    De plus, ils connaissent leur catalogue.

    En conséquence de quoi, sans plus d'informations sur le besoin effectif, j'aurais tendance à modéliser comme suit :
    * une table dictionnaire des Taux de TVA applicables en ce moment (pour les listes déroulantes)
    * une information dans la table produits "Taux de Tva par défaut"
    * une information dans la table des lignes de factures "taux de tva appliquée"
    La table dictionnaire n'étant pas contrainte en tant que reference de FK.

    L'inconvénient de cette modélisation est la zone de flou sur l'application du "bon" taux de TVA au jour du changement de règles.

    Comme, la modélisation est une affaire de point de vue et/ou compréhension du sujet, ne pas hésiter à argumenter
    Le savoir est une nourriture qui exige des efforts.

  18. #18
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 717
    Points : 31 028
    Points
    31 028
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Michel.Priori Voir le message
    Comme, la modélisation est une affaire de point de vue et/ou compréhension du sujet, ne pas hésiter à argumenter
    J'ai eu une fois à créer une bdd pour gérer une librairie. Il y avait donc les produits (livres/papeterie), les éditeurs (en autojointure car certains éditeurs sont fournisseurs pour d'autres éditeurs), et bien évidemment une table TVA (ce n'est pas parce qu'ici j'ai donné un mini-modèle d'exemple pour débutants que je ne suis pas conscient que dans la réalité la TVA doit être déportée).
    Et effectivement j'ai eu à gérer le souci "recherche du passé" dans la mesure où celui qui veut requêter sur les ventes de l'an dernier doit avoir la TVA du jour de la vente et non celle du jour de la requête.
    Je l'ai résolu par une table "historique tva" dans laquelle un trigger placé sur tva venait gérer cette table pour y insérer ou modifier les donnés (oui modifier car avec par exemple 3 changements de TVA dans la même journée, seul le dernier changement doit être gardé).
    Ainsi on pouvait rester en intégrité directe entre "produit" et "tva" (qui effectivement me servait aussi de support pour l'IHM et ses menus déroulants), la table "historique" (ayant elle-aussi une contrainte d'intégrité avec la table "tva") ne servant que lors des requêtes sur le passé.
    En revanche je n'avais jamais songé à la possibilité qu'un produit (ex "kit de jeu de rôle") puisse avoir plusieurs taux à choisir selon le sens du vent...

    Citation Envoyé par Michel.Priori Voir le message
    L'inconvénient de cette modélisation est la zone de flou sur l'application du "bon" taux de TVA au jour du changement de règles.
    La loi est très claire là dessus : toute décision officielle démarre toujours à la date citée à 0h00. Si on dit "la TVA changera le 01/07" alors elle change le 01/07 à 0h. En matière fiscale, le jour ne se divise pas (30° indivisible).
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  19. #19
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 837
    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 837
    Points : 52 927
    Points
    52 927
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    ...
    La loi est très claire là dessus : toute décision officielle démarre toujours à la date citée à 0h00. Si on dit "la TVA changera le 01/07" alors elle change le 01/07 à 0h. En matière fiscale, le jour ne se divise pas (30° indivisible).
    Pas tout à fait... soit la date est citée par décret, soit c'est le lendemain de la parution au journal officiel.

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

  20. #20
    Membre expérimenté
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Septembre 2016
    Messages
    766
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2016
    Messages : 766
    Points : 1 473
    Points
    1 473
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Et effectivement j'ai eu à gérer le souci "recherche du passé" dans la mesure où celui qui veut requêter sur les ventes de l'an dernier doit avoir la TVA du jour de la vente et non celle du jour de la requête.
    Si je comprends bien le modèle, on a :
    * une table TVA
    * une table produits
    * une table vente (ou factures)
    * une table lignes de détail (ou lignes de facture)
    De telle manière que la table de détail stocke l'ID produit, et l'on retrouve le taux de TVA applicable par jeu de requête.

    Perso je préfère stocker directement le taux de TVA appliqué dans la table de détail (ainsi que le prix d'ailleurs).

    Note : il n'y a pas de redondance de donnée car les champs sémantiques des différentes informations relatives à la TVA ne sont pas les mêmes.
    * Tva de référence
    * Tva applicable
    * Tva appliquée


    Note 2 : Dans mon modèle, il faudra utiliser un ordonnanceur (un job) pour mettre à jour les données le jour J.
    Alors que dans le modèle avec les date de début et fin cela sera automatiquement pris en compte à la bonne date.
    **dans un cas comme dans l'autre on est dépendant d'une action antérieure -ordonnancement ou saisie.
    Le savoir est une nourriture qui exige des efforts.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [Python 2.X] Problème de condition : respectée alors qu'elle ne le devrait pas.
    Par Quartman dans le forum Programmation multimédia/Jeux
    Réponses: 4
    Dernier message: 18/02/2015, 02h09
  2. Image de fonds qui bouge (alors qu'elle ne devrait pas)
    Par koukic11 dans le forum Mise en page CSS
    Réponses: 0
    Dernier message: 01/02/2010, 09h57
  3. Réponses: 3
    Dernier message: 30/07/2008, 08h51
  4. Réponses: 2
    Dernier message: 16/08/2007, 09h48
  5. Réponses: 6
    Dernier message: 20/07/2007, 13h16

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