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 MySQL Discussion :

Requête et présentation à l'horizontale


Sujet :

Requêtes MySQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2013
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Retraité
    Secteur : Transports

    Informations forums :
    Inscription : Mars 2013
    Messages : 20
    Par défaut Requête et présentation à l'horizontale
    Bonjour à tous,
    ma base de données, contient deux tables.

    La première table : t_membres contient: les noms (ch_nom) et les prénoms (ch_prenom). Chaque membre possède un numéro unique (ch_no_membre).
    La seconde table : t_cotisation contient: l'année (ch_annee) et le n° de membre (ch_no_membre).
    Dans ce champ (ch_no_membre), la valeur est la même que celle du champ (ch_no_membre) de la table t_membres.
    Ces deux éléments permettent de faire une jonction entre les deux tables.

    Récapitulatif :
    Table t_membres: ch_no_membre, ch_nom, ch_prenom
    Table t_cotisation: ch_no_membre, ch_annee,
    Jonction entre les deux tables avec t_membres.ch_no_membre et t_cotisation.ch_no_membre

    Je souhaite récupérer l’ensemble des années cotisées de tous les membres et les afficher selon le principe suivant :
    id|--Nom | Prénom | 2016 | 2017 | 2018 (ligne des titres)
    1 | Nom(1) | Prén(1) | ----- | 2017 | 2018 (le membre 1 à cotisé en 2017 et 2018
    2 | Nom(2) | Prén(2) | 2016| ------ | 2018 (le membre 2 à cotisé en 2016 et 2018)
    3 | Nom(3) | Prén(3) | ----- | ------ | 2018 (le membre 3 à cotisé en 2018)
    etc....



    J’arrive à récupérer et à afficher les membres ainsi que l'année,
    mais sous le forme suivante: (plusieurs lignes par membre)
    id|--Nom -- | Prénom | 2016 | 2017 | 2018 (ligne des titres)
    1 | Nom(1) | Prén(1) | ----- | 2017 | -------
    1 | Nom(1) | Prén(1) | ----- | ------ | 2018
    2 | Nom(2) | Prén(2) | 2016| ------ | -------
    2 | Nom(2) | Prén(2) | ----- | ------ | 2018
    3 | Nom(3) | Prén(3) | ----- | ------ | 2018

    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
     
                    $choix_tri_sql='
                         SELECT * 
                         FROM t_membres, t_cotisation 
                         WHERE t_membres.ch_no_membre = t_cotisation.ch_no_membre 
                         ORDER BY t_membres.ch_no_membre ASC, t_cotisation.ch_annee';
                    $result = $link->query($choix_tri_sql) or die ('Erreur : '.mysqli_error() );
     
                                  //affichage des résultats.    
                       echo '<table>;
                        while($row = mysqli_fetch_array($result)) {
                              echo '<tr>';
                                echo '<td>'.$row['ch_no_membre'].'&nbsp'.'</td>';
                                echo '<td>'.'&nbsp'.'&nbsp'.$row['ch_nom'].'</td>';
                                echo '<td>'.'&nbsp'.'&nbsp'.$row['ch_prenom'].'</td>';
                                 if ($row['ch_annee']==2016) {echo '<td>'.$row['ch_annee'].'</td>';}
                                    else{echo '<td> </td>';}
                                 if ($row['ch_annee']==2017) {echo '<td>'.$row['ch_annee'].'</td>';}
                                    else{echo '<td> </td>';}
                                  if ($row['ch_annee']==2018) {echo '<td>'.$row['ch_annee'].'</td>';}
                                    else{echo '<td> </td>';}
                            echo '</tr>'."\n";
                          } 
                        echo '</table>'."\n";
    je souhaiterai que chaque membre avec les années cotisées soit affiché sur une seule ligne

    merci d'avance pour votre aide et vos conseils.
    cdt

  2. #2
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 602
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 602
    Billets dans le blog
    10
    Par défaut
    Bonjour

    Il y a une solution simple via auto-jointures sous réserve que vous n'ayez que 3 années à traiter, est-ce que ce sera toujours le cas ?

    Exemple :

    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
       select T1.ch_no_membre                                            
            , T1.ch_nom                                                  
            , T1.ch_prenom                                               
            , case when T2.ch_no_membre is not null then T2.ch_annee end 
            , case when T3.ch_no_membre is not null then T3.ch_annee end 
            , case when T4.ch_no_membre is not null then T4.ch_annee end 
       from t_membres T1                                                       
       left join t_cotisation T2                                                  
         on T2.ch_no_membre=T1.ch_no_membre                              
        and T2.ch_annee=2016                                               
       left join t_cotisation T3                                                    
         on T3.ch_no_membre=T1.ch_no_membre                                
        and T3.ch_annee=2017                                               
       left join t_cotisation T4                                                    
         on T4.ch_no_membre=T1.ch_no_membre                                
        and T4.ch_annee=2018

  3. #3
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 135
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 135
    Par défaut
    Une autre manière de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    SELECT  mbr.ch_no_membre
        ,   mbr.ch_nom
        ,   mbr.ch_prenom
        ,   SUM(CASE ch_annee WHEN 2016 THEN ch_annee END)
        ,   SUM(CASE ch_annee WHEN 2017 THEN ch_annee END)
        ,   SUM(CASE ch_annee WHEN 2018 THEN ch_annee END)
    FROM    t_membres       mbr
        INNER JOIN
            t_cotisation    cts 
            ON  mbr.ch_no_membre = cts.ch_no_membre
    GROUP BY mbr.ch_no_membre
        ,   mbr.ch_nom
        ,   mbr.ch_prenom 
    ORDER BY mbr.ch_no_membre
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  4. #4
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 602
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 602
    Billets dans le blog
    10
    Par défaut
    Le résultat de cette deuxième solution n'est pas exactement le même que celui de ma proposition, sauf à remplacer la jointure INNER par une jointure OUTER

    - la première requête liste tous les membres, y compris ceux n'ayant jamais cotisé
    - la deuxième ne liste que les membres ayant cotisé au moins une année (jointure INNER oblige)

    A vous de choisir selon le besoin

  5. #5
    Membre prolifique Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 884
    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 884
    Par défaut
    Salut à tous.

    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
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    --------------
    SET AUTOCOMMIT = 0
    --------------
     
    --------------
    START TRANSACTION
    --------------
     
    --------------
    DROP DATABASE IF EXISTS `base`
    --------------
     
    --------------
    CREATE DATABASE `base`
        DEFAULT CHARACTER SET `latin1`
        DEFAULT COLLATE       `latin1_general_ci`
    --------------
     
    --------------
    DROP TABLE IF EXISTS `membre`
    --------------
     
    --------------
    CREATE TABLE `membre`
    ( `no_membre`  integer unsigned  not null auto_increment primary key,
      `nom`        varchar(255)      not null,
      `prenom`     varchar(255)      not null
    ) ENGINE=InnoDB
      DEFAULT CHARSET=`latin1` COLLATE=`latin1_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    INSERT INTO `membre` (`nom`,`prenom`) VALUES
      ('Nom 1','Prénom 1'),
      ('Nom 2','Prénom 2'),
      ('Nom 3','Prénom 3'),
      ('Nom 4','Prénom 4'),
      ('Nom 5','Prénom 5')
    --------------
     
    --------------
    select * from `membre`
    --------------
     
    +-----------+-------+----------+
    | no_membre | nom   | prenom   |
    +-----------+-------+----------+
    |         1 | Nom 1 | Prénom 1 |
    |         2 | Nom 2 | Prénom 2 |
    |         3 | Nom 3 | Prénom 3 |
    |         4 | Nom 4 | Prénom 4 |
    |         5 | Nom 5 | Prénom 5 |
    +-----------+-------+----------+
    --------------
    DROP TABLE IF EXISTS `cotisation`
    --------------
     
    --------------
    CREATE TABLE `cotisation`
    ( `id`         integer  unsigned  not null auto_increment primary key,
      `annee`      smallint unsigned  not null,
      `no_membre`  integer  unsigned  not null,
      CONSTRAINT `FK_MEMBRE` FOREIGN KEY (`no_membre`) REFERENCES `membre` (`no_membre`) ON DELETE CASCADE ON UPDATE CASCADE
    ) ENGINE=InnoDB
      DEFAULT CHARSET=`latin1` COLLATE=`latin1_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    INSERT INTO `cotisation` (`annee`,`no_membre`) VALUES
      (2014,1),(2015,1),(2016,1),(2017,1),(2018,1),
      (2015,2),(2017,2),(2018,2),
      (2013,4),(2014,4),(2015,4),
      (2018,5)
    --------------
     
    --------------
    select * from `cotisation`
    --------------
     
    +----+-------+-----------+
    | id | annee | no_membre |
    +----+-------+-----------+
    |  1 |  2014 |         1 |
    |  2 |  2015 |         1 |
    |  3 |  2016 |         1 |
    |  4 |  2017 |         1 |
    |  5 |  2018 |         1 |
    |  6 |  2015 |         2 |
    |  7 |  2017 |         2 |
    |  8 |  2018 |         2 |
    |  9 |  2013 |         4 |
    | 10 |  2014 |         4 |
    | 11 |  2015 |         4 |
    | 12 |  2018 |         5 |
    +----+-------+-----------+
    --------------
    select          t1.no_membre,
                    max(t1.nom)    as nom,
                    max(t1.prenom) as prenom,
                    case when t2.no_membre is not null then max(t2.annee) else '----' end as '2014',
                    case when t3.no_membre is not null then max(t3.annee) else '----' end as '2015',
                    case when t4.no_membre is not null then max(t4.annee) else '----' end as '2016',
                    case when t5.no_membre is not null then max(t5.annee) else '----' end as '2017',
                    case when t6.no_membre is not null then max(t6.annee) else '----' end as '2018'
     
              from  `membre`      as t1
     
    left outer join  `cotisation` as t2
                 on  t2.no_membre = t1.no_membre
                and  t2.annee     = 2014
     
    left outer join  `cotisation` as t3
                 on  t3.no_membre = t1.no_membre
                and  t3.annee     = 2015
     
    left outer join  `cotisation` as t4
                 on  t4.no_membre = t1.no_membre
                and  t4.annee     = 2016
     
    left outer join  `cotisation` as t5
                 on  t5.no_membre = t1.no_membre
                and  t5.annee     = 2017
     
    left outer join  `cotisation` as t6
                 on  t6.no_membre = t1.no_membre
                and  t6.annee     = 2018
     
           group by  t1.no_membre
    --------------
     
    +-----------+-------+----------+------+------+------+------+------+
    | no_membre | nom   | prenom   | 2014 | 2015 | 2016 | 2017 | 2018 |
    +-----------+-------+----------+------+------+------+------+------+
    |         1 | Nom 1 | Prénom 1 | 2014 | 2015 | 2016 | 2017 | 2018 |
    |         2 | Nom 2 | Prénom 2 | ---- | 2015 | ---- | 2017 | 2018 |
    |         5 | Nom 5 | Prénom 5 | ---- | ---- | ---- | ---- | 2018 |
    |         4 | Nom 4 | Prénom 4 | 2014 | 2015 | ---- | ---- | ---- |
    |         3 | Nom 3 | Prénom 3 | ---- | ---- | ---- | ---- | ---- |
    +-----------+-------+----------+------+------+------+------+------+
    --------------
    select          t1.no_membre,
                    max(t1.nom)    as nom,
                    max(t1.prenom) as prenom,
                    max(case t2.annee when 2014 then '2014' else '----' end) as '2014',
                    max(case t2.annee when 2015 then '2015' else '----' end) as '2015',
                    max(case t2.annee when 2016 then '2016' else '----' end) as '2016',
                    max(case t2.annee when 2017 then '2017' else '----' end) as '2017',
                    max(case t2.annee when 2018 then '2018' else '----' end) as '2018'
     
              from  `membre`      as t1
     
    left outer join  `cotisation` as t2
                 on  t2.no_membre = t1.no_membre
     
           group by  t1.no_membre
    --------------
     
    +-----------+-------+----------+------+------+------+------+------+
    | no_membre | nom   | prenom   | 2014 | 2015 | 2016 | 2017 | 2018 |
    +-----------+-------+----------+------+------+------+------+------+
    |         1 | Nom 1 | Prénom 1 | 2014 | 2015 | 2016 | 2017 | 2018 |
    |         2 | Nom 2 | Prénom 2 | ---- | 2015 | ---- | 2017 | 2018 |
    |         4 | Nom 4 | Prénom 4 | 2014 | 2015 | ---- | ---- | ---- |
    |         5 | Nom 5 | Prénom 5 | ---- | ---- | ---- | ---- | 2018 |
    |         3 | Nom 3 | Prénom 3 | ---- | ---- | ---- | ---- | ---- |
    +-----------+-------+----------+------+------+------+------+------+
    --------------
    COMMIT
    --------------
     
    --------------
    SET AUTOCOMMIT = 1
    --------------
     
     
    Appuyez sur une touche pour continuer...
    La seconde requête, celle de Al1_24 me semble être la plus performante, puisqu'elle ne nécessite qu'une seule jointure, à l'inverse de celle d'Escartefigue qui nécessite cinq jointures.

    Je rappelle que le rôle de MySql est d'extraire les informations et non de faire de la présentation comme il est demandé dans ce sujet.

    Comme kolbyt utilise le php, il existe en effet une solution plus basique, qui consiste à gérer une rupture de séquence dans une boucle, afin d'attribuer les années dans les bonnes colonnes d'un tableau.
    Et bien sûr,la requête mysql serait de ce 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
    23
    24
    25
    26
    27
    28
    29
    --------------
    select          t1.no_membre,
                    t1.nom,
                    t1.prenom,
                    t2.annee
     
              from  `membre`      as t1
     
    left outer join  `cotisation` as t2
                 on  t2.no_membre = t1.no_membre
    --------------
     
    +-----------+-------+----------+-------+
    | no_membre | nom   | prenom   | annee |
    +-----------+-------+----------+-------+
    |         1 | Nom 1 | Prénom 1 |  2014 |
    |         1 | Nom 1 | Prénom 1 |  2015 |
    |         1 | Nom 1 | Prénom 1 |  2016 |
    |         1 | Nom 1 | Prénom 1 |  2017 |
    |         1 | Nom 1 | Prénom 1 |  2018 |
    |         2 | Nom 2 | Prénom 2 |  2015 |
    |         2 | Nom 2 | Prénom 2 |  2017 |
    |         2 | Nom 2 | Prénom 2 |  2018 |
    |         4 | Nom 4 | Prénom 4 |  2013 |
    |         4 | Nom 4 | Prénom 4 |  2014 |
    |         4 | Nom 4 | Prénom 4 |  2015 |
    |         5 | Nom 5 | Prénom 5 |  2018 |
    |         3 | Nom 3 | Prénom 3 |  NULL |
    +-----------+-------+----------+-------+
    Dans ce forum, nous traitons exclusivement MySql et rien d'autre.
    Si kolbyt préfère une solution moitié mysql moitié php dans ce cas il doit s'adresses au forum mysql+php.

    @+

  6. #6
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 602
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 602
    Billets dans le blog
    10
    Par défaut
    Citation Envoyé par Artemus24 Voir le message
    La seconde requête, celle de Al1_24 me semble être la plus performante, puisqu'elle ne nécessite qu'une seule jointure, à l'inverse de celle d'Escartefigue qui nécessite cinq jointures.


    On a une solution qui se base sur 3 jointures, une autre sur une jointure plus un regroupement
    Il faut donc considérer les index existants pour savoir si le regroupement nécessitera ou non un tri
    De plus la jointure s'effectue dans un cas sur identifiant unique, dans l'autre sur identifiant partiel

    Difficile donc de se prononcer a priori. Comme souvent, l'exécution en conditions réelles permettra de guider le choix

  7. #7
    Membre prolifique Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 884
    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 884
    Par défaut
    Salut Escartefigue.

    Il est tout à fait normal de mettre en doute ce que je dis, mais bon, je me suis inspiré du explain de mysql, que je donne ci-après :
    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
    69
    70
    71
    --------------
    explain
    select          t1.no_membre,
                    max(t1.nom)    as nom,
                    max(t1.prenom) as prenom,
                    case when t2.no_membre is not null then max(t2.annee) else '----' end as '2014',
                    case when t3.no_membre is not null then max(t3.annee) else '----' end as '2015',
                    case when t4.no_membre is not null then max(t4.annee) else '----' end as '2016',
                    case when t5.no_membre is not null then max(t5.annee) else '----' end as '2017',
                    case when t6.no_membre is not null then max(t6.annee) else '----' end as '2018'
     
              from  `membre`      as t1
     
    left outer join  `cotisation` as t2
                 on  t2.no_membre = t1.no_membre
                and  t2.annee     = 2014
     
    left outer join  `cotisation` as t3
                 on  t3.no_membre = t1.no_membre
                and  t3.annee     = 2015
     
    left outer join  `cotisation` as t4
                 on  t4.no_membre = t1.no_membre
                and  t4.annee     = 2016
     
    left outer join  `cotisation` as t5
                 on  t5.no_membre = t1.no_membre
                and  t5.annee     = 2017
     
    left outer join  `cotisation` as t6
                 on  t6.no_membre = t1.no_membre
                and  t6.annee     = 2018
     
           group by  t1.no_membre
    --------------
     
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
    | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                                              |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
    |  1 | SIMPLE      | t1    | NULL       | ALL  | PRIMARY       | NULL | NULL    | NULL |    5 |   100.00 | Using temporary                                    |
    |  1 | SIMPLE      | t2    | NULL       | ALL  | FK_MEMBRE     | NULL | NULL    | NULL |   13 |   100.00 | Using where; Using join buffer (Block Nested Loop) |
    |  1 | SIMPLE      | t3    | NULL       | ALL  | FK_MEMBRE     | NULL | NULL    | NULL |   13 |   100.00 | Using where; Using join buffer (Block Nested Loop) |
    |  1 | SIMPLE      | t4    | NULL       | ALL  | FK_MEMBRE     | NULL | NULL    | NULL |   13 |   100.00 | Using where; Using join buffer (Block Nested Loop) |
    |  1 | SIMPLE      | t5    | NULL       | ALL  | FK_MEMBRE     | NULL | NULL    | NULL |   13 |   100.00 | Using where; Using join buffer (Block Nested Loop) |
    |  1 | SIMPLE      | t6    | NULL       | ALL  | FK_MEMBRE     | NULL | NULL    | NULL |   13 |   100.00 | Using where; Using join buffer (Block Nested Loop) |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
    --------------
    explain
    select          t1.no_membre,
                    max(t1.nom)    as nom,
                    max(t1.prenom) as prenom,
                    max(case t2.annee when 2014 then '2014' else '----' end) as '2014',
                    max(case t2.annee when 2015 then '2015' else '----' end) as '2015',
                    max(case t2.annee when 2016 then '2016' else '----' end) as '2016',
                    max(case t2.annee when 2017 then '2017' else '----' end) as '2017',
                    max(case t2.annee when 2018 then '2018' else '----' end) as '2018'
     
              from  `membre`      as t1
     
    left outer join  `cotisation` as t2
                 on  t2.no_membre = t1.no_membre
     
           group by  t1.no_membre
    --------------
     
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
    | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                                              |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
    |  1 | SIMPLE      | t1    | NULL       | ALL  | PRIMARY       | NULL | NULL    | NULL |    5 |   100.00 | Using temporary                                    |
    |  1 | SIMPLE      | t2    | NULL       | ALL  | FK_MEMBRE     | NULL | NULL    | NULL |   13 |   100.00 | Using where; Using join buffer (Block Nested Loop) |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
    @+

  8. #8
    Rédacteur/Modérateur
    Avatar de andry.aime
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    8 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Ile Maurice

    Informations forums :
    Inscription : Septembre 2007
    Messages : 8 391
    Par défaut
    Bonjour,

    Le problème avec ces solutions c'est que l'année prochaine tu dois réécrire la requête puisque les années sont codées en dur.

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SET @sql = NULL;
    SELECT
      GROUP_CONCAT(DISTINCT
        CONCAT( 'SUM(CASE annee WHEN ''', annee,''' THEN annee END) as ''', annee,''' ' )
      ) INTO @sql
    FROM
      cotisation;
     
    SET @sql = CONCAT('SELECT  m.no_membre , nom, prenom, ', @sql, ' FROM membre m left join cotisation c on c.no_membre = m.no_membre group by m.no_membre');
    PREPARE stmt FROM @sql;
    EXECUTE stmt;

    A+.

  9. #9
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 602
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 602
    Billets dans le blog
    10
    Par défaut
    Citation Envoyé par Artemus24 Voir le message
    Il est tout à fait normal de mettre en doute ce que je dis, mais bon, je me suis inspiré du explain de mysql, que je donne ci-après
    Sauf erreur de ma part, le besoin est sur 3 années. J'avais d'ailleurs précisé dans ma proposition :

    Citation Envoyé par escartefigue Voir le message
    Bonjour
    Il y a une solution simple via auto-jointures sous réserve que vous n'ayez que 3 années à traiter, est-ce que ce sera toujours le cas ?
    Une requête correspond à un besoin fonctionnel, si ce besoin change, il est possible que la requête change

    De plus, vous avez ajouté un group by inutile pour la 1ère solution

    Sinon, pour des solutions plus complètes, voir les solutions évoquées ici pour SQL Server dont certaines sont utilisables sous MySQL

  10. #10
    Membre averti
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2013
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Retraité
    Secteur : Transports

    Informations forums :
    Inscription : Mars 2013
    Messages : 20
    Par défaut
    Bonjour

    Grand merci à tous pour votre aide et vos conseils
    grâce à vous j'ai réussi à faire mon tableau
    les membres de notre club de planche à voile vont pouvoir en profiter lors de la prochaine AG

    (Désolé si le choix de forum n’était pas des plus judicieux)

    Cordialement

    kolbyt
    Apprenti sorcier en informatique

  11. #11
    Membre prolifique Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 884
    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 884
    Par défaut
    Salut à tous.

    Citation Envoyé par andry.aime
    Le problème avec ces solutions c'est que l'année prochaine tu dois réécrire la requête puisque les années sont codées en dur.
    Pas nécessairement car la mise en forme de la requête peut se faire à l'aide du php, c'est à dire d'une manière automatique.
    Entre autre, sortir les cinq années précédentes d'une manière glissante, sachant que l'année courante est l'année où vous lancez la requête.

    Citation Envoyé par Escartefigue
    Sauf erreur de ma part, le besoin est sur 3 années.
    Quand j'ai lu le premier message de "kolbyt", il disait :
    Citation Envoyé par kolbyt
    Je souhaite récupérer l’ensemble des années cotisées de tous les membres et les afficher selon le principe suivant :
    Kolbyt n'a pas explicitement précisé le nombre des années cotisées, sauf que son exemple est sur trois années.

    Citation Envoyé par Escartefigue
    Une requête correspond à un besoin fonctionnel, si ce besoin change, il est possible que la requête change
    Je suis entièrement d'accord avec vous !
    Mais vu que le problème posée peut avoir plusieurs interprétations (le nombre d'années), il est normal d'avoir un flou dans la réponse finale.

    Citation Envoyé par Escartefigue
    De plus, vous avez ajouté un group by inutile pour la 1ère solution
    Vous avez raison, je suis désolé.

    Je ne dénigne pas votre solution, Escartefigue, je la trouve intéressante, mais selon mon point de vue, elle est moins performante que celle d'Al1_24.

    @+

Discussions similaires

  1. Réponses: 4
    Dernier message: 20/03/2008, 17h23
  2. Arranger la présentation du résultat à une requête SQL
    Par Roy Miro dans le forum Requêtes
    Réponses: 1
    Dernier message: 02/09/2007, 12h11
  3. Réponses: 1
    Dernier message: 17/06/2007, 10h10
  4. SSRS 2005, présentation horizontale ?
    Par olive_olive dans le forum MS SQL Server
    Réponses: 12
    Dernier message: 10/10/2006, 15h19
  5. [MySQL] tableau HTML pour présentation des résultats de requêtes
    Par memel182 dans le forum PHP & Base de données
    Réponses: 8
    Dernier message: 04/07/2006, 14h58

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