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 :

[MySQL] Effectuer une distribution statistique en SQL


Sujet :

Langage SQL

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7
    Points : 7
    Points
    7
    Par défaut [MySQL] Effectuer une distribution statistique en SQL
    Bonjour,

    Je suis confronté à une problématique de "distribution statistique" que j'aimerais résoudre avec une requête SQL.

    Je travaille sur des réseaux sociaux, et je souhaite compter le nombre d'amis de chacun de mes utilisateurs.

    Ce que je sais faire :
    - ramener le nombre d'amis pour chacun de mes utilisateurs
    - ramener le nombre d'utilisateurs ayant 1, 2, ... amis
    - ramener le nombre total d'utilisateurs ayant des amis

    Ce que je souhaite faire :
    - ramener le nombre d'amis (en X) et la répartition en % par rapport au total de mes utilisateurs (en Y) => exemple

    Ma requête actuelle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    select nb_amis, count(util_id) as nb_util
    from (
        select utilisateurs.util_id, count(distinct amis.ami_id) as nb_amis
        from utilisateurs inner join amis on utilisateurs.util_id = amis.util_id
        group by 1
    ) tab
    group by 1;
    Pouvez-vous m'aider ?
    Merci par avance ! :o)

  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
    Comme ça ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT nb_amis, (100 * count(util_id) AS nb_util) / (SELECT COUNT(*) FROM utilisateurs) AS pourcentage
    FROM (
        SELECT utilisateurs.util_id, count(DISTINCT amis.ami_id) AS nb_amis
        FROM utilisateurs INNER JOIN amis ON utilisateurs.util_id = amis.util_id
        GROUP BY utilisateurs.util_id
    ) tab
    GROUP BY nb_amis
    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 confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    hmm attention Cinéphil, ceci est une requête scalaire (edit : remarque vu la répartition .... ca ne sera pas un problème)

    Il vaudrai mieux prendre une option de jointure cartésiène pour ce problème je pense.

    Vu que me MySql ne supporte pas le cross join ..

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    SELECT nb_amis, (100 * count(util_id) AS nb_util) / max(nb_tot) AS pourcentage
    FROM (
        SELECT utilisateurs.util_id, count(DISTINCT amis.ami_id) AS nb_amis
        FROM utilisateurs INNER JOIN amis ON utilisateurs.util_id = amis.util_id
        GROUP BY utilisateurs.util_id
    ) tab,
    (SELECT COUNT(*) as nb_tot FROM utilisateurs) 
    GROUP BY nb_amis

  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
    Euh... il me semble avoir répondu à ça :
    ramener le nombre d'amis et la répartition en % par rapport au total de mes utilisateurs
    Le fait que ce soit en X et en Y n'est pas du ressort du SGBD il me semble.

    Dans ta requête comme dans la mienne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT COUNT(*) AS nb_tot FROM utilisateurs
    Ne donne qu'un seul nombre : le nombre de lignes de la table utilisateurs, c'est à dire le nombre total d'utilisateurs.

    Demander dans ta requête le max(nb_tot) donnera toujours le même nombre !

    J'ai donc l'impression que ta requête donne le même résultat que la mienne mais avec une jointure inutile.
    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
    Membre émérite Avatar de pacmann
    Homme Profil pro
    Consulté Oracle
    Inscrit en
    Juin 2004
    Messages
    1 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consulté Oracle
    Secteur : Distribution

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Points : 2 845
    Points
    2 845
    Par défaut
    Salut !

    D'après ton graphique, tu veux une somme cumulative, donc pour mois il y a deux étapes :
    - Grouper le nombre d'utilisateurs par nombre d'amis
    - Sommer pour chaque nombre d'amis le pourcentage de gens qui ont autant ou moins.

    Sans fonctions analytiques, ça donne un truc du genre :
    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
     
    SELECT tab4.nb_amis, sum(nb_util) / (select count(*) from utilisateurs) pct
    FROM 
        (SELECT nb_amis, count(*) AS nb_util
        FROM (
            SELECT count(amis.ami_id) AS nb_amis
            FROM utilisateurs 
                LEFT OUTER JOIN amis ON utilisateurs.util_id = amis.util_id
            GROUP BY utilisateurs.util_id
        ) tab
        GROUP BY nb_amis) tab2
        JOIN
            (SELECT DISTINCT nb_amis
        FROM (
            SELECT count(amis.ami_id) AS nb_amis
            FROM utilisateurs 
                LEFT OUTER JOIN amis ON utilisateurs.util_id = amis.util_id
            GROUP BY utilisateurs.util_id
        ) tab3
        ) tab4
        ON tab4.nb_amis >= tab2.nb_amis
    GROUP BY tab4.nb_amis
    Punkoff, tu penses que MySQL ré-exécute la requête scalaire à chaque fois ?
    (Sur Oracle je parierais que non)

    (c'est ma photo)
    Paku, Paku !
    Pour les jeunes incultes : non, je ne suis pas un pokémon...

    Le pacblog : http://pacmann.over-blog.com/

  6. #6
    Membre expérimenté
    Homme Profil pro
    Ingenieur de recherche - Ecologue
    Inscrit en
    Juin 2003
    Messages
    1 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingenieur de recherche - Ecologue

    Informations forums :
    Inscription : Juin 2003
    Messages : 1 146
    Points : 1 412
    Points
    1 412
    Par défaut
    Pour faire une digression (sur le plan statistique), le terme de distribution statistique est incorrect.

    La distribution statistique est le représentation des données sous forme graphique pour vérifier quelle suit une loi statistique (gauss, Poisson, etc) - pour faire simple -
    Merci d'ajouter un sur les tags qui vous ont aidé

  7. #7
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    Citation Envoyé par pacmann Voir le message
    Punkoff, tu penses que MySQL ré-exécute la requête scalaire à chaque fois ?
    (Sur Oracle je parierais que non)
    C'est la question que j'essai d'éllucidé en ce moment même
    le trip c'est qu'ici il n'y a qu'un "select count(*) from ma_table" sans référence à l'autre table ... du coup ...


    edit: je ne peux pas tester sur MySql, mais sur 2 autres sgbd ca passe sasn problème.

    Donc je suppose que la solution de Cinephil est mieux (je parle de la technique utilisée pas de la requête à fournir pour résoudre le problème initiale)

  8. #8
    Membre émérite Avatar de pacmann
    Homme Profil pro
    Consulté Oracle
    Inscrit en
    Juin 2004
    Messages
    1 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consulté Oracle
    Secteur : Distribution

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Points : 2 845
    Points
    2 845
    Par défaut
    Citation Envoyé par dehorter olivier Voir le message
    Pour faire une digression (sur le plan statistique), le terme de distribution statistique est incorrect.

    La distribution statistique est le représentation des données sous forme graphique pour vérifier quelle suit une loi statistique (gauss, Poisson, etc) - pour faire simple -
    Ouah, tu chipottes quand même

    La répartition d'une population par modalité, et la version cumulative, c'est la version discrète de ce que tu obtiens en intégrant la loi de probabilité...
    En tous cas, le terme de distribution s'applique bien ici. Après, c'est le mot statistique que tu n'aimes pas ?

    (c'est ma photo)
    Paku, Paku !
    Pour les jeunes incultes : non, je ne suis pas un pokémon...

    Le pacblog : http://pacmann.over-blog.com/

  9. #9
    Membre expérimenté
    Homme Profil pro
    Ingenieur de recherche - Ecologue
    Inscrit en
    Juin 2003
    Messages
    1 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingenieur de recherche - Ecologue

    Informations forums :
    Inscription : Juin 2003
    Messages : 1 146
    Points : 1 412
    Points
    1 412
    Par défaut
    Citation Envoyé par pacmann Voir le message
    Ouah, tu chipottes quand même

    La répartition d'une population par modalité, et la version cumulative, c'est la version discrète de ce que tu obtiens en intégrant la loi de probabilité...
    En tous cas, le terme de distribution s'applique bien ici. Après, c'est le mot statistique que tu n'aimes pas ?
    oui, je sais ET tu as raison, la version cumulative est bien une distribution au sens statistique.


    Sur le plan SQL, je ne suis pas très au point dessus; mais les CTE pourraient être utile dans ce contexte (si elles sont implémentées dans MySql ?)
    Merci d'ajouter un sur les tags qui vous ont aidé

  10. #10
    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
    Eh non ! Pas de récursif chez MySQL !

    Je n'ai pas regardé la requête de Pacman en détail mais j'ai l'impression que ce sera plus rapide de récupérer le paquet de données de ma requête puis de traiter la cumulation dans le langage de programmation en même temps que la construction du graphique.
    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 !

  11. #11
    Membre émérite Avatar de pacmann
    Homme Profil pro
    Consulté Oracle
    Inscrit en
    Juin 2004
    Messages
    1 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consulté Oracle
    Secteur : Distribution

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Points : 2 845
    Points
    2 845
    Par défaut
    Oui s'il y a des problèmes de perf, c'est sûrement ce qu'il y a de mieux à faire... ou alors passer par une table temporaire (toujours pas aussi rapide qu'un traitement itératif sur le premier résultset, mais une fois l'aggrégat enregistré, la requête doit être beaucoup plus légère).

    Olivier, la CTE aurait été utile uniquement sous Oracle, parce qu'elle permet la matérialisation du résultat (c'est à dire la mise en table temporaire "système").

    Mais avant de reprocher ça à MySQL, je reprocherais plutôt l'absence de fonctions analytique qui auraient certainement permis d'écrire le résultat très différemment ! (et plus rapidement bien sûr )

    Par exemple sous Oracle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    SELECT nb_amis, sum(nb_util) OVER(ORDER BY nb_amis) / count(*) OVER(ORDER BY NULL)
    FROM (
           SELECT nb_amis, count(*) nb_util
           FROM (
                SELECT count(b.amis_id) nb_amis
                FROM utilisateurs a
                  LEFT OUTER JOIN amis b ON a.util_id = b.util_id
                GROUP BY a.util_id)
                )
           GROUP BY nb_amis
          )

    (c'est ma photo)
    Paku, Paku !
    Pour les jeunes incultes : non, je ne suis pas un pokémon...

    Le pacblog : http://pacmann.over-blog.com/

Discussions similaires

  1. Réponses: 0
    Dernier message: 21/10/2014, 15h48
  2. Réponses: 2
    Dernier message: 15/12/2011, 16h50
  3. Comment effectuer une requette SQL depuis Excel vers une base MySQL ?
    Par Zorgloub dans le forum Macros et VBA Excel
    Réponses: 9
    Dernier message: 24/01/2008, 01h08
  4. Réponses: 3
    Dernier message: 20/05/2006, 23h28
  5. [MySQL] creer une table SQL
    Par orasia dans le forum Langage SQL
    Réponses: 4
    Dernier message: 29/04/2006, 11h21

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