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 :

Résumer 2 colonnes en une seule


Sujet :

Langage SQL

  1. #1
    Candidat au Club
    Homme Profil pro
    Consultant communication & réseaux
    Inscrit en
    Janvier 2020
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant communication & réseaux
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Janvier 2020
    Messages : 4
    Points : 2
    Points
    2
    Par défaut Résumer 2 colonnes en une seule
    Bonjour à tous,

    L'intitulé du sujet n'est pas très clair, mais j'espère que cela deviendra plus compréhensible avec l'explication qui va suivre.

    Je galère un peu sur une requête SQL.

    J'ai 5 tables :
    - Cable (id_cable)
    - Cable_patch(id_cable, id_chambre, id_boite))
    - cassette (id_cassette, id_chambre)
    - tiroir (id_tiroir, id_boite)
    - Position (id_position,id_tiroir, id_cassette)

    Et voici ma 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
     
    SELECT
        cable.id_cable AS id_cable,
        COALESCE (F3.nb_fibre3, 0) AS nb_position_cassette,
        COALESCE ( F4.nb_fibre4,0) AS nb_position_boite
    FROM
        cable 
            LEFT JOIN (
    		SELECT
    		    cable.id_cable,
    		    COUNT(*) nb_fibre3
    		FROM 
    		    cable
    		        INNER JOIN cable_patch
    		            ON cable.id_cable = cable_patch.id_cable
    		        LEFT JOIN cassette 
    		            ON cable_patch.id_chambre = cassette.id_chambre
    		        LEFT JOIN position
    		            ON cassette.id_cassette =  position.id_cassette
    		GROUP BY cable.id_cable
    	    ) F3
    	    ON cable.id_cable = F3.id_cable
    	LEFT JOIN (
    		SELECT
    		    cable.id_cable,
    		    COUNT (*) nb_fibre4
    		FROM cable
    		    INNER JOIN cable_patch
    		        ON cable.id_cable = cable_patch.id_cable
    		    LEFT JOIN tiroir 
    		        ON  cable_patch.id_boite = t_tiroir.id_boite
    		    LEFT JOIN position 
    		        ON t_tiroir.id_tiroir = position.id_tiroir
    		    GROUP BY cable.id_cable
    	    ) F4
    	    ON cable.id_cable = F4.id_cable
    Cette requête est divisée en 2 "sous-requête", nommée F3 et F4.
    La requête F3 va me donner, pour chaque câble, le nombre de "position" possédant un "id_cassette" (en passant par plusieurs jointures : cable vers cable_patch, cable_patch vers cassette, et cassette vers position)
    La requête F4 va me donner, pour chaque câble, le nombre de "position" possédant un "id_tiroir" (en passant par plusieurs jointures : cable vers cable_patch, cable_patch vers tiroir, et tiroir vers position)
    Du coup, le résultat de ma requête ressemblera à quelque chose comme ça :

    Nom : imageimage.PNG
Affichages : 165
Taille : 5,3 Ko

    Ce que j'aimerais faire, c'est donc résumer les champs "chambre_positif" et "boite_positif" en une seule colonne :
    Chaque câble ne peut pas avoir à la fois des positions possédant un "id_cassette" et un "id_tiroir". Et pour savoir si un câble va avoir des positions possédant un "id_cassette" ou bien un "id_tiroir", il faut aller voir la table "cable_patch".
    Cette table comporte les identifiants de chaque câbles, ainsi que les champs "id_chambre" et "id_boite".

    A partir de là, il n'y a que 2 possibilités :
    - si, dans la table "cable_patch", un câble possède une valeur "id_chambre", ce câble aura des positions de type "id_cassette" que l'on peut récupérer avec les jointures présentes dans ma requête F3.
    - si, dans la table "cable_patch", un câble possède une valeur "id_boite", ce câble aura des positions de type "id_tiroir" que l'on peut récupérer avec les jointures présentes dans ma requête F4.

    J'aimerais donc avoir une seule colonne qui me donnerait, pour chaque câble, le nombre de "position" de type "id_cassette" (en allant donc voir si ce câble possède une valeur "id_chambre" dans la table "cable_patch")
    OU
    qui me donnerait, pour un câble ne possédant aucune valeur "id_chambre" dans "cable_patch", le nombre de "position" de type "id_tiroir" (en allant donc voir si ce câble possède une valeur "id_boite" dans la table "cable_patch").

    J'espère que toutes ces explications ne sont pas trop longue et/ou trop compliquées. Pour résumé, j'aimerais juste transformer mes 2 "sous-requêtes" F3 et F4 qui me donnent deux champs différents en une seule requête qui me donnerait un seul champs.

    Merci d'avance à ceux qui me liront, et n'hésitez pas à me dire si mon problème n'est pas suffisamment clair

  2. #2
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Essayez quelque chose comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        select cb.id_cable
             , greatest(count(pc.id_cassette), count(pt.id_tiroir)) as nb_position
          from cable       as cb
    inner join cable_patch as cp on cp.id_cable    = cb.id_cable
     left join cassette    as cs
    inner join position    as pc on pc.id_cassette = cs.id_cassette
                                 on cs.id_chambre  = cp.id_chambre
     left join tiroir      as tr
    inner join position    as pt on pt.id_tiroir   = tr.id_tiroir
                                 on tr.id_boite    = cp.id_boite
      group by cb.id_cable;

  3. #3
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 947
    Points : 5 846
    Points
    5 846
    Par défaut
    Juste une question Waldar, quand tu écris :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        select ...
          from cable       as cb
    inner join cable_patch as cp on cp.id_cable    = cb.id_cable
     left join cassette    as cs
    inner join position    as pc on pc.id_cassette = cs.id_cassette
                                 on cs.id_chambre  = cp.id_chambre
    C'est la même chose qu'avec sous-requête ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
        select ...
          from cable       as cb
    inner join cable_patch as cp on cp.id_cable    = cb.id_cable
     left join (select cs.id_chambre, ...
                  from cassette as cs
            inner join position as pc on pc.id_cassette = cs.id_cassette 
               ) t
            on t.id_chambre  = cp.id_chambre
    Cette syntaxe est-elle implémentée sur tous les SGBD ?

  4. #4
    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,
    Citation Envoyé par skuatamad Voir le message
    C'est la même chose qu'avec sous-requête ?
    oui

    Citation Envoyé par skuatamad Voir le message
    Cette syntaxe est-elle implémentée sur tous les SGBD ?
    au moins les principaux :
    Oracle, SQL Server, Mysql (attention, sous mysql, s'il manque le 2eme ON, un JOIN devient un CROSS JOIN !) , et PG aussi il me semble.

  5. #5
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 947
    Points : 5 846
    Points
    5 846
    Par défaut
    Merci aieeeuuuuu

  6. #6
    Candidat au Club
    Homme Profil pro
    Consultant communication & réseaux
    Inscrit en
    Janvier 2020
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant communication & réseaux
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Janvier 2020
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Un grand merci pour ta réponse, ça marche nickel

  7. #7
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Citation Envoyé par skuatamad Voir le message
    Juste une question Waldar, quand tu écris :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        select ...
          from cable       as cb
    inner join cable_patch as cp on cp.id_cable    = cb.id_cable
     left join cassette    as cs
    inner join position    as pc on pc.id_cassette = cs.id_cassette
                                 on cs.id_chambre  = cp.id_chambre
    Comme l'a déjà dit aieeeuuuuu oui, mais je préfère plutôt le visualiser comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        select ...
          from cable       as cb
    inner join cable_patch as cp on cp.id_cable    = cb.id_cable
     left join (cassette   as ct
    inner join  position   as pc on pc.id_cassette = ct.id_cassette) as cs
                                 on cs.id_chambre  = cp.id_chambre

  8. #8
    Candidat au Club
    Homme Profil pro
    Consultant communication & réseaux
    Inscrit en
    Janvier 2020
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant communication & réseaux
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Janvier 2020
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Waldar, j'aurais une petite question par rapport à ta requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    select cb.id_cable
             , greatest(count(pc.id_cassette), count(pt.id_tiroir)) as nb_position
          from cable       as cb
    inner join cable_patch as cp on cp.id_cable    = cb.id_cable
     left join cassette    as cs
    inner join position    as pc on pc.id_cassette = cs.id_cassette
                                 on cs.id_chambre  = cp.id_chambre
     left join tiroir      as tr
    inner join position    as pt on pt.id_tiroir   = tr.id_tiroir
                                 on tr.id_boite    = cp.id_boite
      group by cb.id_cable;
    Ma table "position" possède également un champs "fonction".
    Si je veux, par exemple, filtrer les résultats de cette requête en n'ayant que les positions dont la fonction est 'A', comment dois-je faire ?
    Ce qui me perturbe, c'est que la requête utilise la table position 2 fois, et lui donne donc 2 alias différents.
    Je me doute bien qu'utiliser " WHERE pc.fonction = 'A' " ou " WHERE pt.fonction = 'A' " juste avant le GROUP BY me donnera des résultats différents, puisque le filtre ne se fera pas sur la totalité des positions.
    Mais d'un autre côté, " WHERE pc.fonction = 'A' AND pt.fonction = 'A' " ne me donne aucun résultat

  9. #9
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Oui, c'est un "effet de bord" des jointures externes, si vous filtrez dans le WHERE vous faites disparaître l'aspect externe de la jointure (car tous les nulls seront exclus du filtre).
    Vous pouvez faire comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
      select cb.id_cable
             , greatest(count(pc.id_cassette), count(pt.id_tiroir)) as nb_position
          from cable       as cb
    inner join cable_patch as cp  on cp.id_cable    = cb.id_cable
     left join cassette    as cs
    inner join position    as pc  on pc.id_cassette = cs.id_cassette
                                 and pc.fonction    = 'A'
                                  on cs.id_chambre  = cp.id_chambre
     left join tiroir      as tr
    inner join position    as pt  on pt.id_tiroir   = tr.id_tiroir
                                 and pt.fonction    = 'A'
                                  on tr.id_boite    = cp.id_boite
      group by cb.id_cable;

  10. #10
    Candidat au Club
    Homme Profil pro
    Consultant communication & réseaux
    Inscrit en
    Janvier 2020
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant communication & réseaux
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Janvier 2020
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Merci pour ta réponse.
    En effet, filtrer de cette façon marche très bien. Jusque-là, je n'avais jamais dû filtrer autrement qu'avec WHERE, du coup je vais essayer de garder cet effet de bord en tête.
    Encore merci pour ton aide

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

Discussions similaires

  1. Récupérer le contenu de colonnes en une seule ligne
    Par casavba dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 03/07/2008, 13h21
  2. Multiplication d'une colonne par une seul valeur
    Par ANTMA dans le forum Excel
    Réponses: 2
    Dernier message: 28/11/2007, 16h33
  3. Concatener une colonne en une seule ligne.
    Par Contrec dans le forum Oracle
    Réponses: 3
    Dernier message: 12/10/2007, 08h51
  4. Afficher plusieur colonnes sur une seule colonne ?
    Par Interruption13h dans le forum Langage SQL
    Réponses: 4
    Dernier message: 04/02/2007, 16h57
  5. [VBA] Fusionner plusieurs colonnes en une seule
    Par brutos2 dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 18/01/2006, 14h25

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