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 :

SUM sur une jointure à trois tables


Sujet :

Langage SQL

  1. #1
    Membre habitué Avatar de Rapha222
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    128
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2007
    Messages : 128
    Points : 168
    Points
    168
    Par défaut SUM sur une jointure à trois tables
    Salut,
    Je dispose de trois tables comme ceci:

    Le truc, c'est que j'aimerais pour un client donné (ou pour une liste de clients avec une clause GROUP BY client.id) obtenir le nombre de données envoyées et recues (SUM sur le champ bytes, sachant qu'un client peut envoyer ou recevoir plusieurs paquets), mais avec des LEFT JOIN, il croise mes deux tables, ce qui fait que si j'ai 3 enregistrements (pour un client) dans UPLOAD et 5 dans DOWNLOADS, il va me retourner 15 lignes, et moi je n'en voudrais que 5, donc les deux dernières auraient des champs NULL dans UPLOAD (par exemple).
    Comment puis-je faire ça proprement (en une seule requête quoi) ? Il y a bien moyen avec une UNION + deux sous-requêtes, mais ca me retourne tout ca sous forme de lignes et nom de colones, et c'est pas très optimisé.
    Merci

    Je suis avec SQLite

  2. #2
    Membre expérimenté Avatar de Yanika_bzh
    Homme Profil pro
    Responsable Applicatif et R&D
    Inscrit en
    Février 2006
    Messages
    1 144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Responsable Applicatif et R&D
    Secteur : Finance

    Informations forums :
    Inscription : Février 2006
    Messages : 1 144
    Points : 1 738
    Points
    1 738
    Par défaut
    Vous auriez pu avoir une table transfert commune avec une colonne discriminant le type de transfert effectué (Up ou down)

    Dans votre cas, il va falloir le simuler par requete :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    select b.id, sum (case when (a.type = 1) then a.bytes else 0 end) as PacketEnvoyes, sum (case when (a.type = 2) then a.bytes else 0 end) as PacketRecus
    		from
    		(select 1 /* Type envoyé */ as type , client_id, bytes  from  packets_uploads
    		 union
    		select 2 /* Type recu */ as type , client_id, bytes from packets_downloads) a
    		inner join clients b on (b.id = a.client_id)
    		group by b.id
    bon courage

  3. #3
    Membre habitué Avatar de Rapha222
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    128
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2007
    Messages : 128
    Points : 168
    Points
    168
    Par défaut
    Merci,
    J'avais déjà pensé à ça, mais ca m'arrange pas vraiment. En fait j'ai une table TEMPORARY et une normale, d'où un séparation ralativement nécéssaire.
    Pour l'instant je crée une nouvelle table "virtuelle" avec une UNION à chaque requête, mais ca ne me semble pas très propre ...

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

    Informations forums :
    Inscription : Août 2008
    Messages : 2 950
    Points : 5 849
    Points
    5 849
    Par défaut
    Je suis peut etre a la ramasse mais en quoi cette requete ne correspond pas au besoin :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    select c.nom,sum(u.bytes) as nb_upload,sum(d.bytes) as nb_download
    from clients c
    left join packets_uploads u on c.id=u.client_id
    left join packets_downloads d on c.id=d.client_id
    group by c.nom
    Sinon la solution de Yanika_bzh est bien plus propre que de creer des tables temporaires.

  5. #5
    Membre habitué Avatar de Rapha222
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    128
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2007
    Messages : 128
    Points : 168
    Points
    168
    Par défaut
    Citation Envoyé par skuatamad Voir le message
    Je suis peut etre a la ramasse mais en quoi cette requete ne correspond pas au besoin :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    select c.nom,sum(u.bytes) as nb_upload,sum(d.bytes) as nb_download
    from clients c
    left join packets_uploads u on c.id=u.client_id
    left join packets_downloads d on c.id=d.client_id
    group by c.nom
    Sinon la solution de Yanika_bzh est bien plus propre que de creer des tables temporaires.
    Non, je l'ai mis plus haut. Ca va croiser les lignes, donc si j'en ai 5 dans downloads et 2 dans uploads, et si on pose que chaque ligne vaut 1Mo (juste pour l'exemple, elles ont des valeurs différentes en réalité), SUM(d.bytes) et SUM(u.bytes) seroint égales et vaudront 10 toutes les deux, ce qui est faux.

    Une solution pas propre que j'ai trouvée c'est ca:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT SUM(download), SUM(upload) FROM (
       SELECT client_id, SUM(bytes) AS download, 0 AS upload
       FROM downloads GROUP BY client_id
       UNION SELECT client_id, 0 AS download, SUM(bytes) AS upload
       FROM uploads GROUP BY client_id)
    GROUP BY client_id
    Ca m'oblige de refaire toute une table de correspondance des clients, même si je ne souhaite que un seul client (sachant que l'ID du client serait issu d'une sous-requête et non d'une constante, que je pourrais mettre dans les deux requêtes de UNION).

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

    Informations forums :
    Inscription : Août 2008
    Messages : 2 950
    Points : 5 849
    Points
    5 849
    Par défaut
    OK autant pour moi, je visualisais mal ce qui ce passait...
    Perso je prefere la solution de Yanika_bzh qui fait moins de group by.
    Par contre utilise UNION ALL lorsque tu ne souhaites pas faire de DISTINCT.

  7. #7
    Membre habitué Avatar de Rapha222
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    128
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2007
    Messages : 128
    Points : 168
    Points
    168
    Par défaut
    Citation Envoyé par skuatamad Voir le message
    OK autant pour moi, je visualisais mal ce qui ce passait...
    Perso je prefere la solution de Yanika_bzh qui fait moins de group by.
    Par contre utilise UNION ALL lorsque tu ne souhaites pas faire de DISTINCT.
    Ha oui, merci

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

Discussions similaires

  1. Plusieurs SUM sur une même table
    Par fbms18 dans le forum SQL
    Réponses: 6
    Dernier message: 29/04/2011, 10h45
  2. Requete SUM sur une table avec critère sur une autre
    Par wail00 dans le forum Langage SQL
    Réponses: 3
    Dernier message: 21/05/2007, 17h58
  3. limitation du nombre d'enregistrement sur une jointure
    Par coredump dans le forum Langage SQL
    Réponses: 2
    Dernier message: 18/06/2005, 17h13
  4. un count sur une jointure et ca ne fonctionne pas
    Par elbronziero dans le forum Langage SQL
    Réponses: 2
    Dernier message: 14/10/2004, 12h23
  5. Check sur une colonne de table "en cours"
    Par in dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 02/07/2003, 10h47

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