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

 MySQL Discussion :

Requête avec jointure sur 3 tables


Sujet :

MySQL

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 816
    Points : 49
    Points
    49
    Par défaut Requête avec jointure sur 3 tables
    Bonjour à tous,

    Je dispose de 3 tables,
    Table personnel ( avec ID > id_rhp)
    Table rh_personnel_conges_periode (avec ID id_rhpcp)
    Table rh_personnel_conges (Avec ID> id_rhpc et ID id_rhp et id_rhpcp)

    Dans la table "personnel" il y a la liste des salariés, dans la table "période conges" il y a les periodes de conges :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    id_rhpcp|date_debut_acquis|date_fin_acquis|date_debut_utilisable|date_fin_utilisable|Description
    1 	2015-06-01 	2016-05-31 	2016-06-01 	2017-05-31 	Congés acquis en 2015-2016 utilisable en 2016-2017
    2 	2016-06-01 	2017-05-31 	2017-06-01 	2018-05-31 	Congés acquis en 2016-2017 utilisable en 2017-2018
    3 	2017-06-01 	2018-05-31 	2018-06-01 	2019-05-31 	Congés acquis en 2017 2018 utilisable en 2018-2019
    4 	2018-06-01 	2019-05-31 	2019-06-01 	2020-05-31 	Congés acquis en 2018-2019 utilisable en 2019-2020
    5 	2019-06-01 	2020-05-31 	2020-06-01 	2021-05-31 	Congés acquis en 2019-2020 utilisable en 2020-2021
    6 	2020-06-01 	2021-05-31 	2021-06-01 	2022-05-31 	Congés acquis en 2020-2021 utilisable en 2021-2022
    table rh_personnel_conges :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    id_rhp 	debut_conges 	fin_conges 	id_rhptc 	nombre_jour 	id_users 	id_rhpcp 	nbre_samedi
    52 	        2017-08-14 	2017-09-03 	1 	18 	                       1 	   2 	            3
    Depuis la une page web un salarié fait une demande de congés (date de debut et fin de conges) et il doit indiquer sur quelle compte de conges ("periode conges") on doit lui déduire ces jours.

    Je voudrais réaliser une requête qui affiche pour un salarié toutes ces périodes avec les jours congés prises sur ces périodes.

    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
     
    SELECT description, sum(nombre_jour) as nbrejours,sum(nbre_samedi) as nbresamedi,
    date_entree,
    case
    WHEN YEAR(DATE_SUB(periode_fin_acquis, INTERVAL TO_DAYS(date_entree) DAY)) < '1' then  ((MONTH(periode_fin_acquis)- MONTH(date_entree)))*2.5
    WHEN YEAR(DATE_SUB(periode_fin_acquis, INTERVAL TO_DAYS(date_entree) DAY)) < '20' then  30
    WHEN YEAR(DATE_SUB(periode_fin_acquis, INTERVAL TO_DAYS(date_entree) DAY)) >= '30' then 33
    WHEN YEAR(DATE_SUB(periode_fin_acquis, INTERVAL TO_DAYS(date_entree) DAY)) >= '25' then 32
    WHEN YEAR(DATE_SUB(periode_fin_acquis, INTERVAL TO_DAYS(date_entree) DAY)) >= '20' then 31
    else '0' end as jour_acquis
    FROM rh_personnel_conges_periode rhpcp 
    RIGHT JOIN rh_personnel_conges rhpc  on rhpcp.id_rhpcp=rhpc.id_rhpcp
    RIGHT JOIN rh_personnel rhp on rhp.id_rhp=rhpc.id_rhp
    WHERE rhpc.id_rhp='52'
    GROUP BY rhpc.id_rhpcp, description
    Dans mon exemple cela n'affiche qu'une ligne car dans la table "rh_personnel_conges" je n'ai qu'une ligne,mais voudrais arriver l'ensemble des "periode de conges" ci-dessous en exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Description|Date Entrée|Periode fin acquis
    Congés acquis en 2015-2016 utilisable en 2016-2017|1984-01-01 	2016-05-31 	null 	33
    Congés acquis en 2016-2017 utilisable en 2017-2018|1984-01-01 	2017-05-31 	18 	33
    Congés acquis en 2017 2018 utilisable en 2018-2019|1984-01-01 	        2018-05-31 	null 	33
    Congés acquis en 2018-2019 utilisable en 2019-2020|1984-01-01 	2019-05-31 	null 	33
    Congés acquis en 2019-2020 utilisable en 2020-2021|1984-01-01 	2020-05-31 	null 	33
    Congés acquis en 2020-2021 utilisable en 2021-2022|1984-01-01 	2021-05-31 	null 	33
    Est-ce réalisable ? Ou bien faut-il passer par plusieurs requêtes

    merci d'avance pour vos conseils

    guigui69

  2. #2
    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
    Ça ne serait pas plutôt un LEFT JOIN qu'il faudrait utiliser ?

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 816
    Points : 49
    Points
    49
    Par défaut
    Pardon,

    la requete indiqué n'etait pas la derniere car comme j'avais fait plusieurs essai :
    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
     
    SELECT description, sum( nombre_jour ) AS nbrejours, sum( nbre_samedi ) AS nbresamedi, date_entree,
    CASE
    WHEN YEAR( DATE_SUB( periode_fin_acquis, INTERVAL TO_DAYS( date_entree )
    DAY ) ) < '1'
    THEN (
    (
    MONTH( periode_fin_acquis ) - MONTH( date_entree )
    )
    ) * 2.5
    WHEN YEAR( DATE_SUB( periode_fin_acquis, INTERVAL TO_DAYS( date_entree )
    DAY ) ) < '20'
    THEN 30
    WHEN YEAR( DATE_SUB( periode_fin_acquis, INTERVAL TO_DAYS( date_entree )
    DAY ) ) >= '30'
    THEN 33
    WHEN YEAR( DATE_SUB( periode_fin_acquis, INTERVAL TO_DAYS( date_entree )
    DAY ) ) >= '25'
    THEN 32
    WHEN YEAR( DATE_SUB( periode_fin_acquis, INTERVAL TO_DAYS( date_entree )
    DAY ) ) >= '20'
    THEN 31
    ELSE '0'
    END AS jour_acquis
    FROM rh_personnel_conges_periode rhpcp
    LEFT JOIN rh_personnel_conges rhpc ON rhpcp.id_rhpcp = rhpc.id_rhpcp
    LEFT JOIN rh_personnel rhp ON rhp.id_rhp = rhpc.id_rhp
    WHERE rhpc.id_rhp = '52'
    GROUP BY rhpc.id_rhpcp, description
    LIMIT 0 , 30
    Même en LEFT je n'ai qu'une ligne de résultat.

  4. #4
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 381
    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 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut guigui69.

    Citation Envoyé par guigui69
    Je voudrais réaliser une requête qui affiche pour un salarié toutes ces périodes avec les jours congés prises sur ces périodes.
    Voici le genre de résultat que vous devez avoir :

    1) la table du salarié. Pour l'exemple, on mettra :
    --> un identifiant auto_incrémenté.
    --> le nom du salarié.

    2) la table des congés posés du salarié.
    Chaque ligne contiendra le début de la période et la fin de la période de sa prise de congés.
    --> il est nécessaire d'indiquer le salarié. Cela implique que cette colonne soit une clef étrangère.
    --> début de la période posé
    --> fin de la période posé.
    --> un identifiant auto incrémenté car le salarié ne pose pas une seule période de congés.

    3) la table des congés pris par le salarié.
    Chaque ligne contiendra le début de la période ouverte et la fin de la période ouverte effectivement consommé par le salarié.
    --> il est nécessaire d'indiquer le salarié. Cela implique que cette colonne soit une clef étrangère.
    --> début de la période ouverte
    --> fin de la période ouverte.
    --> nombre de jours posés.
    --> un identifiant auto incrémenté car le salarié ne pose pas une seule période de congés.

    A vrai dire, les deux tables des congés ont la même structure, mais ne désigne pas exactement la même période.
    Pour les congés posés, la période est plus grande et englobe les week-end.
    Pour les congés pris, la période est plus courte et ne tient compte que des jours ouverts, et donc effectivement pris.

    Voici le genre de résultat que l'on peut obtenir :
    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
    --------------
    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 `salarie`
    --------------
     
    --------------
    CREATE TABLE `salarie`
    ( `id`     integer unsigned  not null auto_increment primary key,
      `nom`    varchar(255)      not null
    ) ENGINE=InnoDB
      DEFAULT CHARSET=`latin1` COLLATE=`latin1_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    insert into `salarie` (`nom`)  values  ('marcel'),('durant'),('albert')
    --------------
     
    --------------
    select * from `salarie`
    --------------
     
    +----+--------+
    | id | nom    |
    +----+--------+
    |  1 | marcel |
    |  2 | durant |
    |  3 | albert |
    +----+--------+
    --------------
    DROP TABLE IF EXISTS `conges`
    --------------
     
    --------------
    CREATE TABLE `conges`
    ( `id`       integer unsigned  not null auto_increment primary key,
      `deb`      date              not null,
      `fin`      date              not null,
      `salarie`  integer unsigned  not null,
      CONSTRAINT `FK_CONGES_SALARIE` FOREIGN KEY (`salarie`) REFERENCES `salarie` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
    ) ENGINE=InnoDB
      DEFAULT CHARSET=`latin1` COLLATE=`latin1_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    insert into `conges` (`deb`,`fin`,`salarie`)  values
      ('2017-02-18', '2017-02-26', 1),
      ('2017-05-13', '2017-05-21', 1),
      ('2017-01-07', '2017-01-22', 2),
      ('2017-04-29', '2017-05-07', 2),
      ('2017-03-04', '2017-03-12', 3),
      ('2017-06-02', '2017-06-02', 3)
    --------------
     
    --------------
    select * from `conges`
    --------------
     
    +----+------------+------------+---------+
    | id | deb        | fin        | salarie |
    +----+------------+------------+---------+
    |  1 | 2017-02-18 | 2017-02-26 |       1 |
    |  2 | 2017-05-13 | 2017-05-21 |       1 |
    |  3 | 2017-01-07 | 2017-01-22 |       2 |
    |  4 | 2017-04-29 | 2017-05-07 |       2 |
    |  5 | 2017-03-04 | 2017-03-12 |       3 |
    |  6 | 2017-06-02 | 2017-06-02 |       3 |
    +----+------------+------------+---------+
    --------------
    DROP TABLE IF EXISTS `pris`
    --------------
     
    --------------
    CREATE TABLE `pris`
    ( `id`       integer unsigned  not null auto_increment primary key,
      `deb`      date              not null,
      `fin`      date              not null,
      `salarie`  integer unsigned  not null,
      CONSTRAINT `FK_PRIS_SALARIE` FOREIGN KEY (`salarie`) REFERENCES `salarie` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
    ) ENGINE=InnoDB
      DEFAULT CHARSET=`latin1` COLLATE=`latin1_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    insert into `pris` (`deb`,`fin`,`salarie`)  values
      ('2017-02-20', '2017-02-24', 1),
      ('2017-01-09', '2017-01-13', 2),
      ('2017-03-06', '2017-03-06', 3),
      ('2017-03-10', '2017-03-10', 3)
    --------------
     
    --------------
    select * from `pris`
    --------------
     
    +----+------------+------------+---------+
    | id | deb        | fin        | salarie |
    +----+------------+------------+---------+
    |  1 | 2017-02-20 | 2017-02-24 |       1 |
    |  2 | 2017-01-09 | 2017-01-13 |       2 |
    |  3 | 2017-03-06 | 2017-03-06 |       3 |
    |  4 | 2017-03-10 | 2017-03-10 |       3 |
    +----+------------+------------+---------+
    --------------
    select           t2.nom,
                     t1.deb as 'deb_posé',
                     t1.fin as 'fin_posé',
                     t3.deb as 'deb_pris',
                     t3.fin as 'fin_pris'
     
               from  `conges`   as t1
     
         inner join  `salarie`  as t2
                 on  t2.id = t1.salarie
     
    left outer join  `pris`     as t3
                 on  t3.salarie  = t1.salarie
                and  t3.deb     >= t1.deb
                and  t3.fin     <= t1.fin
     
           order by  t2.nom, t1.deb
    --------------
     
    +--------+------------+------------+------------+------------+
    | nom    | deb_posé   | fin_posé   | deb_pris   | fin_pris   |
    +--------+------------+------------+------------+------------+
    | albert | 2017-03-04 | 2017-03-12 | 2017-03-06 | 2017-03-06 |
    | albert | 2017-03-04 | 2017-03-12 | 2017-03-10 | 2017-03-10 |
    | albert | 2017-06-02 | 2017-06-02 | NULL       | NULL       |
    | durant | 2017-01-07 | 2017-01-22 | 2017-01-09 | 2017-01-13 |
    | durant | 2017-04-29 | 2017-05-07 | NULL       | NULL       |
    | marcel | 2017-02-18 | 2017-02-26 | 2017-02-20 | 2017-02-24 |
    | marcel | 2017-05-13 | 2017-05-21 | NULL       | NULL       |
    +--------+------------+------------+------------+------------+
    --------------
    COMMIT
    --------------
     
    --------------
    SET AUTOCOMMIT = 1
    --------------
     
    Appuyez sur une touche pour continuer...
    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

Discussions similaires

  1. Requête SELECT avec jointure sur deux tables
    Par bud64 dans le forum Requêtes
    Réponses: 6
    Dernier message: 01/10/2010, 14h06
  2. Requête SQL avec jointure sur trois tables
    Par pit2121 dans le forum SQL
    Réponses: 0
    Dernier message: 19/05/2008, 20h24
  3. Requête SQL : Jointure sur 3 tables - Bd Access 1997 & Delphi 7
    Par Didier100 dans le forum Bases de données
    Réponses: 2
    Dernier message: 28/12/2007, 09h57
  4. [MySQL] requête avec jointure sur la même table
    Par gwena54 dans le forum PHP & Base de données
    Réponses: 7
    Dernier message: 08/05/2007, 11h22
  5. [ODBC] Pb de requète avec jointure sur 2 bases
    Par Invité dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 12/12/2006, 16h46

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