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

Requêtes PostgreSQL Discussion :

[10] Une jointure de plus ?


Sujet :

Requêtes PostgreSQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre à l'essai
    Homme Profil pro
    Curieux
    Inscrit en
    Octobre 2018
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Curieux
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2018
    Messages : 5
    Par défaut [10] Une jointure de plus ?
    Bonjour.

    OK, le titre n'est pas éloquent, mais je n'avais rien de plus accrocheur ...

    Je vais solliciter votre aide car, pour reprendre une phrase de film célèbre : "J'ai la cervelle en sauce blanche" (Ghostbuster pour les incultes )

    J'ai une requête qui m'a demandé quelques nœuds au cerveau :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
     
    SELECT DISTINCT 
    	documents.id_document,
    	documents.code1,
    	documents.code2,
    	documents.code3,
    	documents.titre,
    	documents.indice,
    	documents.commentaires,
    	documents.fichier_pdf,
    	documents.fichier_source,
    	documents.nb_affaire,
    	etats.etat
    FROM
    	types 
    	INNER JOIN ((((marches INNER JOIN (etats INNER JOIN documents ON etats.id_etat = documents.id_etat)
    	ON marches.id_marche = documents.id_marche) LEFT OUTER JOIN mots_clef ON documents.id_document = mots_clef.id_document)
    	LEFT OUTER JOIN documents_affaires ON documents.id_document = documents_affaires.id_document) INNER JOIN documents_types
    	ON documents.id_document = documents_types.id_document) ON types.id_type = documents_types.id_type
    WHERE
    	(
    		(documents.code1 ILIKE 'Ref1' OR documents.code2 ILIKE 'Ref1' OR documents.code3 ILIKE 'Ref1') --<-param1
    		AND
    		(documents.titre ILIKE '%' OR documents.commentaires ILIKE '%' OR mots_clef.mot_clef ILIKE '%') --<-param2
    		AND
    		marches.marche ILIKE '%' --<-param3
    	)
    	AND
    	     -- Si $4 = 0, c'est que la recherche pointe sur <Tous> les types de documents
    	     1 = CASE
            		WHEN 0 = 0 THEN 1 --<-param4
    		        WHEN types.id_type = 0 THEN 1 --<-param4
    		        ELSE 0
    	     END
            AND
    	      -- Si $6 = 0 c'est que la recherche ne pointe sur aucune affaire
    	      1 = CASE
    		         WHEN 0 =0 THEN 1 --<-param6
    	        	 WHEN documents_affaires.id_affaire = 0 THEN 1 --<-param6
    		         ELSE 0
     	      END
    ORDER BY code1 ASC;
    (Pour être plus précis, il s'agit d'une fonction que j'appelle avec x paramètres. Aussi ne vous formalisez pas des WHEN 0 = 0, il s'agit d'un forçage des paramètres pour ne pas passer par la fonction pour pouvoir faire des tests + rapides sous pgAdmin).
    De plus, désolé pour l'indentation, j'avoue que l'essentiel de la requête a été générée par un soft et que j'ai du mal à démêler les jointures.

    Petites explications :
    J'ai plusieurs tables:
    - 'documents' : liste de documents
    - 'affaires' (un document peut avoir aucune ou plusieurs affaires, une affaire peut avoir aucun ou plusieurs documents)
    - 'types' (un document doit avoir au moins un type, un type peut avoir aucun ou plusieurs document)
    - 'etat' (un document doit avoir un seul état, un état peut avoir aucun ou plusieurs documents)
    - 'mots_clefs' (un document peut avoir aucun ou plusieurs mots_clef, un mot_clef doit avoir un seul document)
    - 'marches' (un document doit avoir un seul marché, un marché peut avoir plusieurs ou aucun document)

    Pour lier tout ça, j'ai 2 tables de liens (excusez si le terme est impropre, j'ai pas fais SQL 1ère langue )
    - 'documents_affaires'
    - 'document_type'

    Actuellement, la fonction... fonctionne . Je récupère bien avec ma requête les info qui m'intéressent :
    En fonction de divers paramètre(param) , je récupère une liste d'enregistrement (normal me direz-vous).

    J'aimerais ajouter une colonne au résultat de la requête correspondant au nombre d'enregistrement ayant l'id_document présents dans la table 'documents_affaires'.

    Exemple :
    la requete trouve 10 enregistrements, je voudrait que pour chaque enregistrement, elle récupère l'id_document (c'est déjà le cas) et qu'elle aille compter le nombre de lignes qui se trouvent dans la table 'documents_affaires' avec le même id_document.

    Je ne pense pas que cela soit très compliqué, une histoire de COUNT(*), mais j'avoue que je sèche. La journée a été longue, c'est peut-être ça ...

    Merci de votre aide bienvenue.

    PS : j'ai omis de préciser que j'étais newbie en programmation (automaticien à la base), idem en SQL, encore plus en PostgreSQL. Des réponses simples, voir un petit exemple seraient vraiment appréciés si vous voulez pas me perdre trop vite

  2. #2
    Membre à l'essai
    Homme Profil pro
    Curieux
    Inscrit en
    Octobre 2018
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Curieux
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2018
    Messages : 5
    Par défaut
    Re,

    J'ai trouvé une solution qui apparemment est fonctionnelle. Par contre, ça fait encore plus usine à gaz.
    Si des aficionado du PostgreSQL pouvait me dire si ça peut être optimisé, j'avoue que je serais pas contre

    Voilà la requête modifiée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
     
    WITH test AS (
    	SELECT DISTINCT 
    		documents.id_document,
    		documents.code1,
    		documents.code2,
    		documents.code3,
    		documents.titre,
    		documents.indice,
    		documents.commentaires,
    		documents.fichier_pdf,
    		documents.fichier_source,
    		etats.etat
    	FROM
    		types 
    		INNER JOIN ((((marches INNER JOIN (etats INNER JOIN documents ON etats.id_etat = documents.id_etat)
    		ON marches.id_marche = documents.id_marche) LEFT OUTER JOIN mots_clef ON documents.id_document = mots_clef.id_document)
    		LEFT OUTER JOIN documents_affaires ON documents.id_document = documents_affaires.id_document) INNER JOIN documents_types
    		ON documents.id_document = documents_types.id_document) ON types.id_type = documents_types.id_type
    	WHERE
    		(
    			(documents.code1 ILIKE '%%' OR documents.code2 ILIKE '%%' OR documents.code3 ILIKE '%%')
    			AND
    			(documents.titre ILIKE '%' OR documents.commentaires ILIKE '%' OR mots_clef.mot_clef ILIKE '%')
    			AND
    			marches.marche ILIKE '%'
    		)
    		AND
    		-- Si $4 = 0, c'est que la recherche pointe sur <Tous> les types de documents
    		1 = CASE
    			WHEN 0 = 0 THEN 1
    			WHEN types.id_type = 0 THEN 1
    			ELSE 0
    		END
    		AND
    		-- Si $6 = 0 c'est que la recherche ne pointe sur aucune affaire
    		1 = CASE
    			WHEN 1 =0 THEN 1 -- <-- J'ai modifié les paramètres de recherche pour chercher les documents liés à cette affaire
    			WHEN documents_affaires.id_affaire = 1 THEN 1-- <-- J'ai modifié les paramètres de recherche pour chercher les documents liés à cette affaire
    			ELSE 0
    		END
    	ORDER BY code1 ASC)
    SELECT 
    	test.id_document,
    	test.code1,
    	test.code2,
    	test.code3,
    	test.titre,
    	test.indice,
    	test.commentaires,
    	test.fichier_pdf,
    	test.fichier_source,
    	test.etat,
    	COUNT(*) AS nb_affaire
    FROM documents_affaires, test WHERE documents_affaires.id_document = test.id_document
    GROUP BY 
    	test.id_document,
    	test.code1,
    	test.code2,
    	test.code3,
    	test.titre,
    	test.indice,
    	test.commentaires,
    	test.fichier_pdf,
    	test.fichier_source,
    	test.etat
    ORDER BY test.id_document;
    Comme spécifié dans le commentaire, j'ai modifié la recherche pour :
    - avoir plus d'une seule ligne
    - avoir des documents liés à plusieurs affaires

    A priori ça fonctionne, mais comme je l'ai dis plus haut, est-ce que c'est "bien écrit" ?

    Merci de vos retours ...

    Cdt

    [EDIT1] : Ah flute ! Ça marche pas en fait ! Je n'ai que les enregistrement avec affaire.

    C'est normal aussi (après réflexion) : dans la table documents_affaires, il n'y a que les documents affectés à une affaire, et pas les autres.
    Il faudrait que si l'id_document n'existe pas dans la table documents_affaires, la valeur de nb_affaire (qui est égale à COUNT(*)) soit mise à 0.


    Bon, j'y retourne ... (bon, je crois que je les ai tous mis...)

    [EDIT2] : Bon j'avance...

    J'ai modifié le second FROM comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    FROM documents_affaires RIGHT OUTER JOIN test ON documents_affaires.id_document = test.id_document
    Je retrouve bien la totalité de mes enregistrement, mais là ou j'attendais un 0, voir un NULL, j'ai une valeur de 1 dans la colonne nb_affaire...
    Work in progress

  3. #3
    Membre à l'essai
    Homme Profil pro
    Curieux
    Inscrit en
    Octobre 2018
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Curieux
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2018
    Messages : 5
    Par défaut
    Bon j'ai trouvé un truc mais là, c'est le bo**el total dans la requête

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
     
    WITH test AS (
    	SELECT DISTINCT 
    		documents.id_document,
    		documents.code1,
    		documents.code2,
    		documents.code3,
    		documents.titre,
    		documents.indice,
    		documents.commentaires,
    		documents.fichier_pdf,
    		documents.fichier_source,
    		etats.etat
    	FROM
    		types 
    		INNER JOIN ((((marches INNER JOIN (etats INNER JOIN documents ON etats.id_etat = documents.id_etat)
    		ON marches.id_marche = documents.id_marche) LEFT OUTER JOIN mots_clef ON documents.id_document = mots_clef.id_document)
    		LEFT OUTER JOIN documents_affaires ON documents.id_document = documents_affaires.id_document) INNER JOIN documents_types
    		ON documents.id_document = documents_types.id_document) ON types.id_type = documents_types.id_type
    	WHERE
    		(
    			(documents.code1 ILIKE '%bla%' OR documents.code2 ILIKE '%bla%' OR documents.code3 ILIKE '%bla%')
    			 AND
    			(documents.titre ILIKE '%' OR documents.commentaires ILIKE '%' OR mots_clef.mot_clef ILIKE '%')
    			AND
    			marches.marche ILIKE '%bbbb%'
    		)
    		AND
    		-- Si $4 = 0, c'est que la recherche pointe sur <Tous> les types de documents
    		1 = CASE
    			WHEN 0 = 0 THEN 1
    			WHEN types.id_type = 0 THEN 1
    			ELSE 0
    		END
    		AND
    		-- Si $6 = 0 c'est que la recherche ne pointe sur aucune affaire
    		1 = CASE
    			WHEN 0 =0 THEN 1
    			WHEN documents_affaires.id_affaire = 0 THEN 1
    			ELSE 0
    		END)
    	--ORDER BY code_edf ASC)
    SELECT 
    	test.id_document,
    	test.code1,
    	test.code2,
    	test.code3,
    	test.titre,
    	test.indice,
    	test.commentaires,
    	test.fichier_pdf,
    	test.fichier_source,
    	test.etat,
    	CASE WHEN documents_affaires.id_document IS NULL THEN 0 ELSE COUNT(*) END AS nb_affaire
    FROM test LEFT OUTER JOIN documents_affaires ON documents_affaires.id_document = test.id_document
    GROUP BY 
    	test.id_document,
    	test.code1,
    	test.code2,
    	test.code3,
    	test.titre,
    	test.indice,
    	test.commentaires,
    	test.fichier_pdf,
    	test.fichier_source,
    	test.etat,
    	documents_affaires.id_document
    ORDER BY test.code1;
    Cherche simplification SVP

  4. #4
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    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 818
    Billets dans le blog
    14
    Par défaut
    Premier début de réponse vite fait parce que ma chérie m'appelle pour l'apéro !

    Voici les jointures remises en forme. Puisque toutes les conditions de jointure utilisent la table documents, je l'ai mise en premier et toutes les jointures en dessous.
    Quel est cet outil merdique qui fout des parenthèses partout ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    FROM documents 
    INNER JOIN types ON types.id_type = documents_types.id_type
    INNER JOIN etats ON etats.id_etat = documents.id_etat
    INNER JOIN marches ON marches.id_marche = documents.id_marche 
    LEFT OUTER JOIN mots_clef ON documents.id_document = mots_clef.id_document
    LEFT OUTER JOIN documents_affaires ON documents.id_document = documents_affaires.id_document 
    INNER JOIN documents_types ON documents.id_document = documents_types.id_document
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    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
    Membre à l'essai
    Homme Profil pro
    Curieux
    Inscrit en
    Octobre 2018
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Curieux
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2018
    Messages : 5
    Par défaut
    Bonsoir CinePhil,

    Citation Envoyé par CinePhil Voir le message
    Premier début de réponse vite fait parce que ma chérie m'appelle pour l'apéro !
    Santé alors !


    Citation Envoyé par CinePhil Voir le message
    Voici les jointures remises en forme. Puisque toutes les conditions de jointure utilisent la table documents, je l'ai mise en premier et toutes les jointures en dessous.


    Citation Envoyé par CinePhil Voir le message
    Quel est cet outil merdique qui fout des parenthèses partout ?
    C'est la fôte à Windev m'sieur ! J'ai fais que r'copier !

    Merci beaucoup pour ce coup de main qui aère le code comme s'est pas permis !

    Il m'a juste fallu modifier légèrement le code que tu m'as fourni et apparemment, tout roule :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    	FROM
    		documents 
    		INNER JOIN documents_types ON documents.id_document = documents_types.id_document   <-- mis en premier sinon la ligne suivante plantait
    		INNER JOIN types ON types.id_type = documents_types.id_type
    		INNER JOIN etats ON etats.id_etat = documents.id_etat
    		INNER JOIN marches ON marches.id_marche = documents.id_marche 
    		LEFT OUTER JOIN mots_clef ON documents.id_document = mots_clef.id_document
    		LEFT OUTER JOIN documents_affaires ON documents.id_document = documents_affaires.id_document

Discussions similaires

  1. Est-ce qu'une jointure avec JOIN est plus rapide que via le WHERE ?
    Par clavier12AZQSWX dans le forum PostgreSQL
    Réponses: 7
    Dernier message: 13/01/2014, 16h31
  2. [CR9] faire une Jointure externe
    Par coldec dans le forum SAP Crystal Reports
    Réponses: 5
    Dernier message: 28/06/2005, 12h10
  3. Comment optimiser une jointure ?
    Par seb_asm dans le forum Administration
    Réponses: 21
    Dernier message: 25/06/2004, 16h42
  4. Lignes en double dans le résultat d'une jointure
    Par ledevelopeur dans le forum Bases de données
    Réponses: 4
    Dernier message: 02/06/2004, 18h10
  5. Une colonne en plus dans ma ListView...
    Par James_ dans le forum C++Builder
    Réponses: 5
    Dernier message: 02/09/2003, 23h30

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