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

MySQL Discussion :

Requete table association


Sujet :

MySQL

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2014
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2014
    Messages : 41
    Points : 25
    Points
    25
    Par défaut Requete table association
    Bonjour tout le monde !

    Voila j'ai un petit problème avec une requête sql.. :/
    Je vous explique le schéma de ma base :
    J'ai 3 tables : la première la table Application composée d'un Id_App, une table Logiciel composée de Id_Logi et Nom_Logi et pour finir une table association entre les deux composées donc de Id_App et Id_Logi.

    Mon objectif est d'afficher le nom et id des logiciels utilisés pour une Application et aussi d'afficher les id et nom des logiciels qui ne sont pas utilisés pour cette même application.

    La première requête très bien aucun problème :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT l.Id_Logiciel, l.Nom_Logiciel
    FROM table_association AS t, logiciel AS l
    WHERE t.Id_Appli =  '$IdAppli'
    AND l.Id_Logiciel = t.Id_Logiciel

    Mais pour la deuxième requête je vois pas trop comment faire je pensais simplement mettre un != ( ou <>) mais le résultat obtenu n'est pas bon et je n'arrive pas à le comprendre.. :/
    Si pouviez me donner un petit indice ça serait vraiment gentil !

    Merci d'avance !

  2. #2
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    1) Les jointures s'écrivent depuis plus de 20 ans avec l'opérateur JOIN ; il serait temps de s'y mettre !

    2) Attention aux injections SQL en donnant directement la variable dans le WHERE sans s'assurer de son type !

    3)
    afficher les id et nom des logiciels qui ne sont pas utilisés pour cette même application.
    Autrement dit : afficher les logiciels pour lesquels il n'existe pas d'association avec une certaine application.
    => Il faut donc utiliser NOT EXISTS.

    Je vous laisse chercher un peu ; ce genre de demande a déjà été faite et résolue maintes fois dans ce forum.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  3. #3
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Bonjour hugerma.

    Quand vous formulez une demande essayez d'être précis dans la description de votre schéma. Voici vos trois tables :
    Application (Id_Appli, Nom_appli)
    Logiciel (Id_Logi, Nom_Logi)
    Association (Id_Appli, Id_Logi)

    Vous avez deux tables pères, qui sont Application et Logiciel, avec respectivement la clef primaire Id_Appli pour Application et Id_Logi pour Logiciel.

    La table fils Association possède une clef primaire sur le couple (Id_Appli, Id_Logi).
    Autrement dit, votre table Association a deux parents. De ce fait, il y a deux clefs étrangères :
    --> une Id_Appli vers la table application.
    --> une Id_Logi vers Logiciel.

    Dans ce que vous recherchez, la table Application ne vous sert à rien, à moins d'extraire le nom de l'application.

    Les deux requêtes ont exactement la même structure. La différence sera que l'un aura 'exists' et l'autre aura 'not exist'.

    Voici une solution possible à votre demande :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    select l.Id_Logi, l.Nom_Logi
    from Logiciel as l
    where exists (	select 1
    		from Association as a
    		where a.Id_Logi = l.Id_logi
    		and   a.Id_Appli like 'votre chaine de caractère'
    	 );
    Exists est un prédicat qui teste une variable logique (un boolean).
    '1' est l'équivalent de 'true'. Si cela n'existe pas, la valeur retrouné est 0, l'équivalent de 'false'.
    Donc quand vous mettez 'exists' la valeur testé doit être 'true' et pour 'not exists', la valeur testé doit être 'false'.
    C'est une erreur de mettre 'select *' au lien de mettre 'select 1' comme on le voie fréquemment.

    J'espère avoir répondu à votre attente.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  4. #4
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    C'est une erreur de mettre 'select *' au lien de mettre 'select 1' comme on le voie fréquemment.
    Euh... non !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    select l.Id_Logi, l.Nom_Logi
    from Logiciel as l
    where exists (	select 1
    		from Association as a
    		where a.Id_Logi = l.Id_logi
    		and   a.Id_Appli like 'votre chaine de caractère'
    	 );
    Cette requête signifie :
    Sélectionner les logiciels pour lesquels il existe une ligne dans la table association où l'application ressemble à "votre chaîne de caractères".

    Et de plus, si "votre chaîne de caractères" n'a pas de caractère générique, inutile d'utiliser LIKE, il vaut mieux utiliser =.

    Dans la sous-requête EXISTS ou NOT EXISTS, on peut mettre ce qu'on veut dans le SELECT (du moment que c'est syntaxiquement correct, bien sûr). SELECT *, SELECT 1, SELECT toto, ça n'a aucune importance puisque ce n'est pas ce SELECT qui est testé mais seulement les conditions du WHERE.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  5. #5
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut Cinephil.

    Je n'ai jamais dit qu'il y avait un problème syntaxique. En effet, tu peux mettre ce que tu veux et même compliquer à outrance ! Mais je ne parle pas de cela !

    La question que l'on doit se poser est double :
    1) Quel est l'utilité d'extraire des colonnes si tu ne t'en sers pas ?
    2) Quel est l'influence de la performance sur un "select *" vis-à-vis d'un "select 1" ?

    J'ai peut-être de vieilles habitudes venant du DB2 (IBM Z/OS) , mais on m'a toujours dit sur un EXISTS de mettre un "select 1". Alors autant mettre la forme la plus concise.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  6. #6
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    2) Quel est l'influence de la performance sur un "select *" vis-à-vis d'un "select 1" ?
    Aucune, dans le cas de l'utilisation dans une sous-requête suivant un comparateur (NOT) EXISTS.

    Voilà ce que dit SQLPro à ce sujet :
    il convient de toujours utiliser l'étoile comme unique contenu de la clause SELECT de la sous-requête car dans ce cas particulier, le moteur SQL choisit une constante la plus adaptée à un traitement performant.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2014
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2014
    Messages : 41
    Points : 25
    Points
    25
    Par défaut
    Salut !

    Merci à vous deux pour votre aide !

    J'ai suivi les conseils de CinePhil qui me disait de regarder du cÔté de NOT EXISTS et j'ai fait ma requête qui ressemble à celle de Artemus24 !

    Donc un grand merci à vous deux !

    Comme toujours ce forum est d'une grande aide !

  8. #8
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut à tous.

    @ Cinephil : Et '1' ce n'est pas une constante, par hasard ?

    @ hugerma : je suis heureux d'avoir pu t'aider.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  9. #9
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    @ Cinephil : Et '1' ce n'est pas une constante, par hasard ?
    Oui, et alors ?

    Tu avais écrit :
    C'est une erreur de mettre 'select *' au lien de mettre 'select 1' comme on le voie fréquemment.
    Et j'ai simplement pointé le fait que non, ce n'est pas une erreur. C'est même ce que conseille SQLPro.

    Ensuite, tu as demandé :
    2) Quel est l'influence de la performance sur un "select *" vis-à-vis d'un "select 1" ?
    Et j'ai répondu : "Aucune".
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  10. #10
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut Cinephil.

    Citation Envoyé par Cinephil
    Oui, et alors ?
    Et bien j'impose à MySql la solution que je considère comme la plus pertinente.

    Je crois que l'on a un problème de communication, car tu me reprends pour dire exactement la même chose que moi.
    A moins que ta définition de la constante ne soit pas la même que chez moi. Avec cette solution, le sous-sélect s'arrête dès la récupération de la première occurrence.

    En gros système (DB2 Z/OS), l'usage de l'étoile sur un select est strictement interdite dans les programmes. Pourquoi ?
    Car si on vient à ajouter une nouvelle colonne, il faut intervenir dans tous les programmes qui utilise cette table pour l'ajouter.
    Donc on évite de s'octroyer du travail supplémentaire en maintenance.
    D'où l'importance des méthodologies de développement que vous ne devez pas connaitre en micro ou mini système.
    Je te rappelle que la volumétrie n'est pas comparable entre ce que tu stockes sur un micro et ce que l'on a en ligne sur un gros système.
    Donc si dès le départ, on a de mauvaise habitude, cela se ressent sur les performances.
    Et oui, je reconnais que j'ai quelques habitudes que l'on m'a vivement conseillé d'appliquer.

    En terme de performance (d'un point de vue général), il est quand même mieux de récupérer uniquement ce dont tu as besoin, en donnant la liste des colonnes.
    Est-ce simplement une question de fainéantise, de privilégier un "select *" plutôt que d'écrire "select col1, col2, col3 ..." ? J'ai l'impression que oui.
    Et il y a la notion de lecture physique et de lecture logique qui passe par dessus la tête de beaucoup d'administrateur. Mais cela c'est une autre histoire.

    Tout ce que je veux dire, ce n'est pas parce que c'est autorisé de le faire, que c'est forcément bien de le faire.
    Et comme tu dois le savoir, à un problème donné, il n'y a pas qu'une seule solution possible.
    La seule façon de prouver ce genre d'écriture (ou de syntaxe), c'est de faire des tests d'optimisations.
    Donc si, selon toi, ça ne change rien de mettre un "select *" et quand terme de performance c'est équivalent à un "select 1", alors pourquoi rejeter cette solution ?
    Surtout qu'en plus, tu affirmes "que le moteur MySql choisit une constante la plus adaptée à un traitement performant".
    Et qu'est-ce qui te dit, justement que mettre "1", ce n'est pas la solution la mieux adaptée ?
    Il n'est pas toujours pertinent de suivre des recommandations si l'on n'a pas la preuve de leur utilité.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  11. #11
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Bonjour,

    Je pense que le plus performant ici serait même de faire les deux requêtes en une, avec une jointure externe :

    sur le principe :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT l.Id_Logiciel, l.Nom_Logiciel, CASE WHEN t.Id_Logiciel IS NULL THEN 'non utilisé' ELSE 'utilisé' END AS utilisation
    FROM logiciel AS l
    LEFT OUTER JOIN table_association AS t
        ON l.Id_Logiciel = t.Id_Logiciel
        AND t.Id_Appli =  '$IdAppli'

  12. #12
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Citation Envoyé par Artemus24 Voir le message
    Salut Cinephil.


    Et bien j'impose à MySql la solution que je considère comme la plus pertinente.
    C'est ton droit mais ça ne change rien.

    Je crois que l'on a un problème de communication, car tu me reprends pour dire exactement la même chose que moi.
    Non. Tu dis que c'est une erreur de mettre un SELECT * dans une sous-requête d'une clause (NOT) EXISTS et je prétends que ce n'en est pas une.

    A moins que ta définition de la constante ne soit pas la même que chez moi.
    Cela n'a rien à voir avec la définition d'une constante et je pense qu'on a la même.

    Avec cette solution, le sous-sélect s'arrête dès la récupération de la première occurrence.
    Dans le cadre du (NOT) EXISTS, il ne s'agit pas de récupérer un résultat mais de tester un résultat. Et effectivement, pour chaque ligne de la requête principale testée, dès que le (NOT) EXISTS est satisfait, le SGBD passe à la ligne suivante, contrairement à la jointure où le SGBD va faire la jointure puis faire le test du WHERE.

    En gros système (DB2 Z/OS), l'usage de l'étoile sur un select est strictement interdite dans les programmes.
    Je ne sais pas si c'est une interdiction par le SGBD que vous mentionnez mais en tout cas c'est effectivement une bonne pratique d'éviter la guerre des étoiles dans la requête principale ou les sous-requêtes en jointure mais dans une sous-requête faisant l'objet du test d'un (NOT) EXISTS, encore une fois, cela n'a aucune importance ! La clause (NOT) EXISTS ne ramène qu'un résultat booléen, pas la ou les colonnes qui seraient écrites derrière le SELECT (ou implicites avec l'étoile).

    Pourquoi ?
    Car si on vient à ajouter une nouvelle colonne, il faut intervenir dans tous les programmes qui utilise cette table pour l'ajouter.
    Donc on évite de s'octroyer du travail supplémentaire en maintenance.
    D'accord avec ça pour le cas général du SELECT *, bien expliqué dans l'article sur la guerre des étoiles mentionné plus haut.

    D'où l'importance des méthodologies de développement que vous ne devez pas connaitre en micro ou mini système.
    Rien à voir avec la méthodologie de développement ici. On parle ici du fonctionnement du (NOT) EXISTS !

    Je te rappelle que la volumétrie n'est pas comparable entre ce que tu stockes sur un micro et ce que l'on a en ligne sur un gros système.
    Évidemment mais ça n'a aucun rapport avec le sujet dont on discute ici.

    En terme de performance (d'un point de vue général), il est quand même mieux de récupérer uniquement ce dont tu as besoin
    Donc, ici, avec un (NOT) EXISTS, uniquement un booléen, pas une série de colonnes, même avec un SELECT *.

    Tout ce que je veux dire, ce n'est pas parce que c'est autorisé de le faire, que c'est forcément bien de le faire.
    Dans le cadre du (NOT) EXISTS, ce n'est pas non plus mal ; ce n'est pas une erreur d'écrire SELECT *.

    Donc si, selon toi, ça ne change rien de mettre un "select *" et quand terme de performance c'est équivalent à un "select 1", alors pourquoi rejeter cette solution ?
    Ai-je dit que je la rejetais ? J'ai seulement fait remarquer que SQLPro préconise le SELECT * dans un (NOT) EXISTS.

    Surtout qu'en plus, tu affirmes "que le moteur MySql choisit une constante la plus adaptée à un traitement performant".
    1) Ce n'est pas moi qui le dit, c'est SQLPro dans son article.
    2) Il n'a pas écrit ça spécifiquement pour le SGBD qu'il appelle MySQmerde mais en général pour tous les SGBD.

    Et qu'est-ce qui te dit, justement que mettre "1", ce n'est pas la solution la mieux adaptée ?
    Et qu'est-ce qui te dit que c'est la meilleure ?
    Apparemment, tu confonds le SELECT * dans un (NOT) EXISTS et le SELECT * général qui est, nous sommes d'accords, à proscrire pour les raison évoquées dans l'article linké plus haut.

    Il n'est pas toujours pertinent de suivre des recommandations si l'on n'a pas la preuve de leur utilité.
    Applique donc cet adage à toi-même !
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  13. #13
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut cinephil.

    Tu as l'art de me faire passer pour quelqu'un qui ne maitrise pas son sujet.
    Il est vrai que je ne suis qu'un transfuge du DB2 Z/OS et que j'applique quelques règles que j'ai apprise sur un autre SGBD.
    Je reconnais que j'ai télescopé deux idées, à savoir les performances et les méthodologies d'écritures imposées par les administrateurs dans les entreprises que j'ai fréquenté.
    Mais en quoi ces règles sont-elles mauvaises, selon toi, puisque ça fait des années qu'on continue de les appliquer avec succès ?

    Citation Envoyé par Cinephil
    C'est ton droit mais ça ne change rien.
    Mais qu'est-ce qui ne change rien ? C'est là où nous avons un problème de communication et tu ne te justifies pas sur ce point.
    C'est peut être moi qui m'exprime mal alors je vais faire simple.

    Tu dis que cela revient au même, je dis oui et non à la fois !
    Oui, car on aura bien une constante comme le préconise MySql.
    Et Non car dans ma solution, j'impose ce choix, pour éviter à MySql de le faire.
    Je trouve sur ce point, qu'il y a une perte de temps en laissant MySql procéder à un choix que je peux dès le départ éviter.
    Donc mon problème n'est pas une question syntaxique mais bien une question de performance.

    C'est exactement le même genre de problème avec les conversions numérique en programmation.
    Pourquoi laisser le compilateur faire des conversions quand on peut dès le départ les éviter ?
    Cela ne te semble pas opportun, mais ce genre de problème à un impact sur les performances. Et c'est tout ce que je dis !

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  14. #14
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Tu as l'art de me faire passer pour quelqu'un qui ne maitrise pas son sujet.
    Pas forcément. J'ai simplement l'impression que tu fondes ton principe intangible sur la confusion de deux cas de SELECT *.

    Il est vrai que je ne suis qu'un transfuge du DB2 Z/OS et que j'applique quelques règles que j'ai apprise sur un autre SGBD.
    Peu importe ! En l'occurrence, ma remarque était générale à tous les SGBD, de même que ce qu'a écrit SQLPro à ce sujet.

    Je reconnais que j'ai télescopé deux idées, à savoir les performances et les méthodologies d'écritures imposées par les administrateurs dans les entreprises que j'ai fréquenté.
    Il semble que tu aies téléscopé deux idées, mais pas forcément celles que tu dis. Voir ma première remarque au début de ce message.

    Mais en quoi ces règles sont-elles mauvaises, selon toi, puisque ça fait des années qu'on continue de les appliquer avec succès ?
    Où ai-je dit qu'elles sont mauvaise ? Et de quelles règles parles-tu dans cette question ?
    Oui, c'est mal d'écrire SELECT * FROM la_table. Voir l'article sur la guerre des étoiles linké dans mon précédent message.
    Non, ce n'est pas une erreur d'utiliser SELECT * dans un (NOT) EXISTS.

    Mais qu'est-ce qui ne change rien ?
    Le fait d'écrire SELECT 1 ou SELECT * dans un (NOT) EXISTS.

    Tu dis que cela revient au même, je dis oui et non à la fois !
    Oui, car on aura bien une constante comme le préconise MySql.
    Ce n'est pas MySQL qui le préconise, c'est le fonctionnement même du (NOT) EXISTS qui fait que le résultat de cette clause est un booléen.

    Je trouve sur ce point, qu'il y a une perte de temps en laissant MySql procéder à un choix que je peux dès le départ éviter.
    Donc mon problème n'est pas une question syntaxique mais bien une question de performance.
    As-tu testé pour l'affirmer ainsi ?

    C'est exactement le même genre de problème avec les conversions numérique en programmation.
    Pourquoi laisser le compilateur faire des conversions quand on peut dès le départ les éviter ?
    Rien à voir avec le sujet qui nous occupe ici.
    Si tu fais allusion aux types des colonnes, bien sûr qu'il faut les choisir avec soin et que, par exemple, une date s'enregistre dans une colonne de type DATE et pas dans une chaîne de caractères ou sous forme d'entier pour ensuite la triturer avec des fonctions non natives du SGBD.

    Cela ne te semble pas opportun, mais ce genre de problème à un impact sur les performances.
    Où ai-je dit que ce n'est pas opportun ? Oui, le dernier problème, hors sujet, que tu cites a un impact sur les performances. En principe, ce n'est pas le cas du SELECT * ou du SELECT 1 dans un (NOT) EXISTS.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  15. #15
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut Cinephil.

    C'est la prise de tête avec toi !!!!

    Citation Envoyé par Cinephil
    Le fait d'écrire SELECT 1 ou SELECT * dans un (NOT) EXISTS.
    Tu affirmes qu'ils sont équivalents alors que je dis exactement le contraire.

    Autrement dit, en mettant "select *", MySql récupère une ligne avant de le convertir en un booléen.
    Tandis qu'en mettant "select 1", il n'y a aucune récupération puisque ce n'est pas demandé, et l'on passe directement au booléen si la ligne existe.

    Donc selon toi, le "select *" ne fonctionnerait pas de la même façon selon l'usage que l'on en fait ?

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  16. #16
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Autrement dit, en mettant "select *", MySql récupère une ligne avant de le convertir en un booléen.
    Non, il ne récupère pas une ligne.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT t1.une_colonne
    FROM une_table t1
    WHERE NOT EXISTS
    (
    	SELECT *
    	FROM une_autre_table t2
    	WHERE t2.id_une_table = t1.id
    )
    Cette requête se traduit par :
    "Sélectionner une_colonne des lignes de une_table pour lesquelles il n'existe pas de ligne dans une_autre_table sur la condition d'égalité entre une_autre_table.id_une_table et une_table.id."

    Ça ne se traduit pas par :
    "Sélectionner une_colonne des lignes de une_table pour lesquelles il n'existe pas de sélection de toutes les colonnes de une_autre_table satisfaisant la condition d'égalité entre une_autre_table.id_une_table et une_table.id."

    D'ailleurs, cette dernière phrase tordue ne signifierait pas grand chose.

    Le SGBD se contente de tester la condition du WHERE de la sous-requête pour chercher si des lignes correspondent avec ce qui est sélectionné dans la requête principale. Dès qu'il trouve dans une_autre_table une ligne associée à la ligne testée dans une_table, EXISTS renvoie 1 (ou true, peu importe) et passe à au test de la ligne de une_table suivante. Si c'est une instruction EXISTS, toutes les une_table.une_colonne ayant obtenu 1 au test sont conservées et si c'est NOT EXISTS ce sont celles qui ne satisfont pas le test qui sont conservées et retournée par la requête globale.

    Donc selon toi, le "select *" ne fonctionnerait pas de la même façon selon l'usage que l'on en fait ?
    Ben oui.
    Ici, le SELECT * veut dire "Sélectionner une ligne" (répondant à la condition de la sous-requête) alors que das le cas général, le SELECT * qui est à proscrire signifie "Sélectionner toutes les colonnes".
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  17. #17
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut CinePhil.

    Encore une fois, tu ramènes cela à une question de syntaxe et non au comportement réel de l'accès aux données.
    Sur une table correctement créé, tu as toujours deux étapes.

    1) la première étape consiste à lire dans les index où se trouve la donnée physique. Oui mais, de quel index s'agit-il ?
    2) la seconde étape permet d'accéder physiquement sur le disque afin de récupérer la ligne.

    En faisant un "select *", tu fais obligatoirement les deux étapes. Pourquoi ? Car tu demandes à récupérer une ligne.

    Tandis, qu'avec un "select 1", tu n'as pas besoin de récupérer quoi que ce soit, puisque tu ne le demandes pas.
    Et de ce fait, l'existence de la ligne se trouve confirmer seulement par l'accès à l'index. Pourquoi ?
    Car l'index utilisé ici est celui du where ! C'est ce genre de comportement que j'ai appris en faisant du DB2.

    Donc si tu ne mets pas d'index sur le where, les deux select sont équivalents car il lira obligatoirement la ligne pour appliquer le where.
    Tandis qu'avec un index, la seconde étape est inutile puisque l'information du where est déjà stockée dans l'index.
    Et comme tu ne désires pas récupérer autre chose, il n'accède pas à la ligne physique.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  18. #18
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Citation Envoyé par Artemus24 Voir le message
    Encore une fois, tu ramènes cela à une question de syntaxe et non au comportement réel de l'accès aux données.
    J'ai plutôt fait de la sémantique que de la syntaxe dans mon précédent message.
    Que ça te plaise ou non, ma requête est syntaxiquement juste au regard de la norme SQL.

    Sur une table correctement créé, tu as toujours deux étapes.

    1) la première étape consiste à lire dans les index où se trouve la donnée physique. Oui mais, de quel index s'agit-il ?
    Justement, reprenons ma requête du message précédent :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT t1.une_colonne
    FROM une_table t1
    WHERE NOT EXISTS
    (
    	SELECT *
    	FROM une_autre_table t2
    	WHERE t2.id_une_table = t1.id
    )
    Le SGBD va tester la condition WHERE t2.id_une_table = t1.id.
    Il va donc rapprocher les index de la clé primaire 'id' de une_table (alias t1) et de la clé étrangère 'id_une_table' de une_autre_table (alias t2).
    Jusque là, pas d'accès aux données de la table.
    Chaque t1.id va être cherché dans t2.id_une_autre_table. Si aucune correspondance est trouvée, alors t1.id sera conservé, dès que le SGBD trouve t1.id dans t2.id_une_table, il ne retient pas le t1.id dans son jeu de résultats et passe au t1.id suivant.
    Quand il aura tout testé, il aura une série de t1.id qui répondent à la condition écrite dans le NOT EXISTS.

    2) la seconde étape permet d'accéder physiquement sur le disque afin de récupérer la ligne.
    En l'occurrence, à l'aide de son jeu de t1.id retenus, il va récupérer les valeurs correspondantes dans t1.une_colonne pour construire son jeu de résultat final.

    En faisant un "select *", tu fais obligatoirement les deux étapes. Pourquoi ? Car tu demandes à récupérer une ligne.
    Tu vois bien que non puisque le SGBD ne s'intéresse à aucun moment aux données détaillées de une_autre_table mais seulement à son index de clé étrangère !
    On se fout que dans t2 il y ait 2 ou 25 colonnes, le SGBD n'ira jamais chercher ces valeurs.

    Tandis, qu'avec un "select 1", tu n'as pas besoin de récupérer quoi que ce soit, puisque tu ne le demandes pas.
    J'espère que tu comprends maintenant qu'avec SELECT * non plus !

    Et de ce fait, l'existence de la ligne se trouve confirmer seulement par l'accès à l'index. Pourquoi ?
    Car l'index utilisé ici est celui du where ! C'est ce genre de comportement que j'ai appris en faisant du DB2.
    De quel WHERE parles-tu dans le cas présent ?
    Le WHERE de la sous-requête est la vraie condition qui est testée. Le WHERE de la requête principale n'est là que pour dire au SGBD : "je te retourne 1 (ou true, peu importe) pour cette ligne, tu peux aller récupérer ce dont tu as besoin pour le SELECT t1.une_colonne."

    Donc si tu ne mets pas d'index sur le where,
    Euh... un index sur le WHERE ? Un index est posé sur une colonne ou un ensemble de colonnes !

    Tandis qu'avec un index, la seconde étape est inutile puisque l'information du where est déjà stockée dans l'index.
    Et comme tu ne désires pas récupérer autre chose, il n'accède pas à la ligne physique.
    C'est ce que je viens d'expliquer plus haut : le SGBD ne s'intéressera jamais aux valeurs de t2, donc on peut écrire SELECT *, SELECT 1 ou SELECT toto, ça n'a aucune importance.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  19. #19
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut Cinephil.

    Citation Envoyé par Artemus24
    C'est une erreur de mettre 'select *' au lien de mettre 'select 1' comme on le voie fréquemment.
    Où ai-je parlé de syntaxe ici ?

    Citation Envoyé par Cinephil
    Que ça te plaise ou non, ma requête est syntaxiquement juste au regard de la norme SQL.
    Je n'ai jamais dit qu'elle était fausse syntaxiquement parlant. Depuis le départ, je parle de performance et du fonctionnement des accès aux tables.

    [quote)Cinephil"]Le SGBD va tester la condition WHERE t2.id_une_table = t1.id.
    Il va donc rapprocher les index de la clé primaire 'id' de une_table (alias t1) et de la clé étrangère 'id_une_table' de une_autre_table (alias t2)[/quote]
    D'abord tu ne prends pas le bon exemple. Depuis le départ, le sujet est centré sur la demande de hugerma. Ce dont on parle concerne la sélection suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    select l.Id_Logi, l.Nom_Logi
    from Logiciel as l
    where exists (	select 1
    		from Association as a
    		where a.Id_Logi = l.Id_logi
    		and   a.Id_Appli like 'votre chaine de caractère'
    	 );
    MySql commence toujours par traiter la table ayant la restriction la plus forte. C'est-à-dire celle donnant le moins de ligne à traiter en premier. Ici, c'est "Association".
    Il va commencer par traiter la condition "a.Id_Appli like 'votre chaine de caractère'".

    Si l'index existe (sur la colonne "a.Id_Appli"), nul besoin d'accéder à la ligne physique car la valeur est déjà présente dans l'index.
    Inversement, si l'index n'existe pas, un accès physique à la ligne est obligatoire pour récupérer le contenu de la colonne "a.Id_Appli".
    Admettons que l'index existe sur cette colonne ("a.Id_Appli").

    Sur le sous ensemble obtenu, il va ensuite pratiquer l'autre restriction "a.Id_Logi = l.Id_logi", et ceci est une jointure.
    Et c'est là que nous avons un problème car le premier index ne sait pas faire le lien entre la colonne "a.Id_Appli" et l'une des deux autres colonnes "a.Id_Logi" & "l.Id_logi".
    Une lecture physique est obligatoire afin de faire le lien entre le premier index ("a.Id_Appli") et l'index de la clef étrangère de la même table.

    Mais si par exemple, tu avais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    select l.Id_Logi, l.Nom_Logi
    from Logiciel as l
    where exists (	select 1
    		from Association as a
    		where a.Id_Logi = l.Id_logi
    		and   a.Id_Logi = "un logiciel"
    	 );
    le problème est complètement différent. D'abord cette requête n'est pas correctement écrite. Tu dois remonter la restriction (ce qui est en rouge) dans le select du dessus.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    select l.Id_Logi, l.Nom_Logi
    from Logiciel as l
    where l.Id_Logi = "un logiciel"
    and   exists (	select 1
    		from Association as a
    		where a.Id_Logi = l.Id_logi
    	 );
    Ensuite MySql va appliquer la restriction la plus forte et de ce fait, commence par traiter la table "Logiciel".
    Dans le sous-select, il n'y a pas de restriction, mais juste une jointure, nul besoin de lire physiquement les lignes, car tout ce dont MySql a besoin ce trouve dans l'index de la clef étrangère.
    La lecture physique des lignes de la table du sous-select se fait, lorsqu'on a une restriction sur une des colonnes de cette table car il n'existe aucun lien entre l'index de la colonne où l'on pratique la restriction et celle de la clef étrangère.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  20. #20
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut Cinephil.

    J'aurai dû commencer par lire la doc MySql.

    Traditionally, an EXISTS subquery starts with SELECT *, but it could begin with SELECT 5 or SELECT column1 or anything at all. MySQL ignores the SELECT list in such a subquery, so it makes no difference.
    Mysql ignore le select et de ce fait, la syntaxe n'a aucune importance. Je constate qu'il y a bien des différences de fonctionnement entre DB2 et MySql.
    Il faut dire que je connais DB2 à une époque où le z/os n'existait pas encore, et ce, dans les années 80.
    Que les différentes versions successives se sont enrichies d'améliorations, que nous n'avons pas répercuté, tout en continuant à utiliser des astuces qui n'avaient plus lieu d'être.

    Même si la syntaxe reste très similaire et respecte la nomenclature SQL, aussi bien avec DB2 et MySql, le fonctionnement peut parfois différer de part les choix des développeurs.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

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

Discussions similaires

  1. [MySQL-5.5] Requete sur table associative
    Par dojbouli dans le forum Requêtes
    Réponses: 4
    Dernier message: 21/08/2013, 11h55
  2. Requete Table croisée ?
    Par zorglob dans le forum Oracle
    Réponses: 2
    Dernier message: 22/12/2005, 12h18
  3. question sur les requetes table héritée
    Par champion dans le forum PostgreSQL
    Réponses: 5
    Dernier message: 30/08/2004, 14h19
  4. creation table association reflexive
    Par elea1206 dans le forum Requêtes
    Réponses: 2
    Dernier message: 05/08/2003, 17h30
  5. Recherche de donnee dans une table associée
    Par josoft dans le forum Requêtes
    Réponses: 2
    Dernier message: 14/07/2003, 15h22

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