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 :

Selection de créneaux horaires


Sujet :

Requêtes MySQL

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

    Informations forums :
    Inscription : Octobre 2006
    Messages : 100
    Points : 64
    Points
    64
    Par défaut Selection de créneaux horaires
    Salut à tous,

    j'utilise un agenda avec plusieurs calendriers pour gérer les reservation de mes voitures. A chaque voiture correspond un calendrier. Pour chaque reservation, j'enregistre un évènement, avec une date de début et une date de fin. Dans ma base j'utilise 2 tables

    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
     
    CREATETABLEIFNOTEXISTS `cal_my_calendrier` (
      `ID` mediumint(255) unsignedNOTNULLAUTO_INCREMENT,
      `titre`varchar(255)NOTNULL,
      PRIMARYKEY(`ID`)
    ) ENGINE=InnoDB DEFAULTCHARSET=latin1 AUTO_INCREMENT=4 ;
     
     
    INSERTINTO`cal_my_calendrier` (`ID`, `titre`)VALUES
    (1,'Voiture_ clio1'),
    (2,'Voiture_ clio2'),
    (3,'Voiture_ clio3');
     
    CREATETABLEIFNOTEXISTS `cal_my_events` (
      `Id_event` mediumint(255) unsignedNOTNULLAUTO_INCREMENT,
      `calendrier` mediumint(255) unsignedDEFAULTNULL,
      `titre`varchar(255)DEFAULTNULL,
      `date_debut`timestampNOTNULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP,
      `date_fin` datetimeDEFAULTNULL,
      PRIMARYKEY(`Id_event`)
    ) ENGINE=InnoDB DEFAULTCHARSET=latin1 AUTO_INCREMENT=6 ;
     
     
    INSERTINTO`cal_my_events` (`Id_event`, `calendrier`, `all_day`, `date_debut`, `date_fin`)VALUES
    (1, 1, 0,'2013-05-08 03:00:00','2013-05-08 12:00:00'),
    (2, 1, 0,'2013-05-09 03:00:00','2013-05-09 08:00:00'),
    (3, 2, 0,'2013-05-08 06:00:00','2013-05-08 18:00:00'),
    (4, 3, 0,'2013-05-05 06:00:00','2013-05-10 18:00:00'),
    (5, 2, 0,'2013-05-10 08:00:00','2013-05-10 10:00:00');
    Je cherche à faire afficher les créneaux ou toutes mes voitures sont occupées, mais je seche complètement. Avec l'exemple fourni, il faudrait que ca m'affiche :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Tableau des créneaux occupés
    +----+----------------------+---------------------+
    | id | debut                | fin                 |
    +----+----------------------+---------------------+
    |  1 | 2013-05-08 06:00:00  | 2013-05-08 12:00:00 |
    J'ai essayé de traiter le problème en SQL ou en PHP via des tableaux, mais je n'arrive à rien

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    100
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 100
    Points : 64
    Points
    64
    Par défaut
    En lisant ce topic

    http://www.developpez.net/forums/d52...neau-horraire/

    et ce cours

    http://sqlpro.developpez.com/cours/gestiontemps/#L1.2.2

    j'en suis arrivé à cette 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 
            cal_my_events.date_debut,
            cal_my_events.date_fin,
            cal_my_events.titre
            FROM
            cal_my_events
            INNER JOIN
                (
                    SELECT
                    date_debut AS debutfirst,
                    date_fin AS finfirst,
                    cal_my_calendrier.ID AS calReference
                    FROM
                    cal_my_events
                    INNER join
                    cal_my_calendrier
                    ON
                    cal_my_events.calendrier=cal_my_calendrier.ID
                    WHERE 
                    cal_my_calendrier.titre LIKE '".$prefixe."%'
                    GROUP BY cal_my_calendrier.ID
                    LIMIT 0,1
                ) AS FirstQuery
            INNER join
            cal_my_calendrier
            ON
            cal_my_events.calendrier=cal_my_calendrier.ID
            WHERE 
            cal_my_calendrier.titre LIKE 'Voiture_%' 
            AND cal_my_calendrier.ID!=calReference
            AND (
                (debutfirst > date_debut AND (debutfirst < date_fin OR finfirst < date_fin)) OR
                (date_debut > debutfirst AND (date_debut < finfirst OR date_fin < finfirst)) OR
                (debutfirst = date_debut AND (finfirst IS NOT NULL AND date_fin IS NOT NULL))
                )
    Ca me renvoie bien un résultat, mais pas le bon

  3. #3
    Membre averti
    Profil pro
    Administrateur
    Inscrit en
    Mai 2008
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Administrateur
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2008
    Messages : 237
    Points : 433
    Points
    433
    Par défaut
    Cette partie de la requête est erronée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    WHERE cal_my_calendrier.titre LIKE '".$prefixe."%'
    Remplacer par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    WHERE cal_my_calendrier.titre LIKE '"' . $prefixe . '"%'

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    100
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 100
    Points : 64
    Points
    64
    Par défaut
    Salut manzeki,

    Merci pour ta réponse. En fait j’exécute ma requête depuis un fichier PHP, ce qui me donne
    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
     
    <?php
    $prefixe="VE_VP";
     
    		$sql="SELECT 
    		cal_my_events.date_debut,
    		cal_my_events.date_fin,
    		cal_my_events.titre
    		FROM
    		cal_my_events
    		INNER JOIN
    			(
    				SELECT
    				date_debut AS debutfirst,
    				date_fin AS finfirst
    				FROM
    				cal_my_events
    				INNER join
    				cal_my_calendrier
    				ON
    				cal_my_events.calendrier=cal_my_calendrier.ID
    				WHERE 
    				cal_my_calendrier.titre LIKE '".$prefixe."%'
     
    			) AS FirstQuery
    		INNER join
    		cal_my_calendrier
    		ON
    		cal_my_events.calendrier=cal_my_calendrier.ID
    		WHERE 
    		cal_my_calendrier.titre LIKE '".$prefixe."%' 
     
    		AND (
    			(debutfirst > date_debut AND (debutfirst < date_fin OR finfirst < date_fin)) OR
    			(date_debut > debutfirst AND (date_debut < finfirst OR date_fin < finfirst)) OR
    			(debutfirst = date_debut AND (finfirst IS NOT NULL AND date_fin IS NOT NULL))
    			)
    	";
    Je ne pense pas que l'erreur vienne de la...

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    100
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 100
    Points : 64
    Points
    64
    Par défaut
    salut,

    je suis complètement bloqué avec cette histoire. Personne n'a déjà eu à faire à ce genre de besoin ? Peut-être que ce n'est pas possible uniquement avec du SQL, mais qu'avec un peu de PHP on devrait s'en sortir. Mais la non plus je n'ai aucune idée

  6. #6
    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,

    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
     
    SELECT 
            A.date_debut as debut,
            MIN(B.Date_Fin) as fin 
    FROM   cal_my_events A
    INNER JOIN cal_my_events B
        ON B.date_debut <= A.Date_debut
        AND B.Date_fin >= A.Date_debut
    GROUP BY A.Date_debut
    HAVING COUNT(*) = (SELECT COUNT(*) FROM cal_my_calendrier)
    Mais il faudrait spécifier le comportement voulu si des plage commencent et ou finissent en même temps...

    Donc testez bien ce code pour différents cas particuliers...

  7. #7
    Membre averti
    Profil pro
    Administrateur
    Inscrit en
    Mai 2008
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Administrateur
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2008
    Messages : 237
    Points : 433
    Points
    433
    Par défaut
    Citation Envoyé par gussoner Voir le message
    salut,

    je suis complètement bloqué avec cette histoire. Personne n'a déjà eu à faire à ce genre de besoin ? Peut-être que ce n'est pas possible uniquement avec du SQL, mais qu'avec un peu de PHP on devrait s'en sortir. Mais la non plus je n'ai aucune idée
    Je ne pense pas que les tables soient bien définies ou bien modélisées.
    Table cal_my_calendrier : que contient le champ titre ?
    Table cal_my_events : que contiennent les champs calendrier, titre ?

    Pourquoi titre dans les deux tables ?

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    100
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 100
    Points : 64
    Points
    64
    Par défaut
    Bonjour,

    Je ne pense pas que les tables sont bien définies ou bien modélisées.
    Table cal_my_calendrier : que contient le champ titre ?
    Table cal_my_events : que contiennent les champs calendrier, titre ?

    Pourquoi titre dans les deux tables ?
    ma table cal_my_calendrier contient la liste de tous mes calendriers. Plusieurs centaines à terme.
    La table cal_my_events contient tous mes événements. Ils ont tous un titre et sont ratachés à un calendrier.


    aieeeuuuuu, j'ai essayé mais ca ne m'a donné aucun résultat...

  9. #9
    Membre averti
    Profil pro
    Administrateur
    Inscrit en
    Mai 2008
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Administrateur
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2008
    Messages : 237
    Points : 433
    Points
    433
    Par défaut
    Citation Envoyé par gussoner Voir le message
    Bonjour,


    ma table cal_my_calendrier contient la liste de tous mes calendriers. Plusieurs centaines à terme.
    La table cal_my_events contient tous mes événements. Ils ont tous un titre et sont ratachés à un calendrier.


    aieeeuuuuu, j'ai essayé mais ca ne m'a donné aucun résultat...
    Je bute sur vos champs titres
    Pourquoi une jointure sur les champs titres. Pourquoi les titres son préfixés par voiture_, ....

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    100
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 100
    Points : 64
    Points
    64
    Par défaut
    mon agenda ne me sert pas uniquement ne me sert pas uniquement à gérer le planning de reservation de mes voitures. Il sert à beaucoup de choses. Pour gérer mes voitures, j'ai un calendrier par voiture. Le titre de chaque calendrier commence par voiture_. Ainsi je recupere mes evenements de la table cal_my_events qui appartiennent à un calendrier qui commence par voiture_ pour avoir uniquement les evenements qui concernent mes voitures

  11. #11
    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
    Citation Envoyé par gussoner Voir le message
    aieeeuuuuu, j'ai essayé mais ca ne m'a donné aucun résultat...
    J'ai essayé aussi, et ça donne bien un résultat, et le bon...

    d'après ce que vous dites, vous avez dû adapter la requête j'imagine... postez la !
    Si vous avez des lignes qui concernent autre chose dans la table cal_my_calendrier, alors effectivement, le requête ne doit pas fonctionner, essayez ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    SELECT 
            A.date_debut AS debut,
            MIN(B.Date_Fin) AS fin 
    FROM   cal_my_events A
    INNER JOIN cal_my_events B
        ON B.date_debut <= A.Date_debut
        AND B.Date_fin >= A.Date_debut
    WHERE A.titre LIKE 'Voiture%'
    AND B.titre LIKE 'Voiture%'
    GROUP BY A.Date_debut
    HAVING COUNT(*) = (SELECT COUNT(*) FROM cal_my_calendrier WHERE titre LIKE 'Voiture%')
    Mais ce bricolage avec le titre qui commence par "Voiture_" est une très mauvaise idée et finira par se sentir au niveau des performances. Pourquoi ne créez vous pas une colonne pour typer les évènements ?

  12. #12
    Membre averti
    Profil pro
    Administrateur
    Inscrit en
    Mai 2008
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Administrateur
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2008
    Messages : 237
    Points : 433
    Points
    433
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    Mais ce bricolage avec le titre qui commence par "Voiture_" est une très mauvaise idée et finira par se sentir au niveau des performances. Pourquoi ne créez vous pas une colonne pour typer les évènements ?
    En effet, l'usage des champs titre comme filtre est une mauvaise idée. Il est normal de créer un champ type_evenement, et mettre un index dessus pour de meilleures performances, de simplification de requête et d'évolution de la base de donnée.

    Si cal_my_calendrier.ID est bien unique, on mettra type_evenement seulement dans la table cal_my_calendrier

  13. #13
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    100
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 100
    Points : 64
    Points
    64
    Par défaut
    J'ai essayé aussi, et ça donne bien un résultat, et le bon...
    Effectivement ca fonctionne bien. Ca ne fonctionnait pas car j'avais une trentaine d'entrée dans cal_my_calendrier, du coup ca ne me renvoyait rien

    Mais ce bricolage avec le titre qui commence par "Voiture_" est une très mauvaise idée et finira par se sentir au niveau des performances. Pourquoi ne créez vous pas une colonne pour typer les évènements ?
    La difficulté est que je ne peux pas intervenir au niveau de mon module agendas. Il est le même pour tous mes utilisateurs et je ne peux rien modifier de ce coté la, c'est pourquoi j'avais pensé à cette solution.

    Mais c'est vrai que je peux faire comme me suggère manzeki. Lors de la création du calendrier, avant l'enregistrement, je vérifie le nom donné par l'utilisateur. S'il contient "voitures_", je lui attribue une valeur sur un nouveau champ type_evenement. Mais en quoi ce sera plus efficace de faire un filtre sur mon champ type_evenement plutôt que sur titre LIKE 'Voiture%' ? C'est le "LIKE" qui est pas terrible ?

    Au passage j'ai découvert sqlfiddle

  14. #14
    Membre averti
    Profil pro
    Administrateur
    Inscrit en
    Mai 2008
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Administrateur
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2008
    Messages : 237
    Points : 433
    Points
    433
    Par défaut
    Citation Envoyé par gussoner Voir le message
    Mais c'est vrai que je peux faire comme me suggère manzeki. Lors de la création du calendrier, avant l'enregistrement, je vérifie le nom donné par l'utilisateur. S'il contient "voitures_", je lui attribue une valeur sur un nouveau champ type_evenement. Mais en quoi ce sera plus efficace de faire un filtre sur mon champ type_evenement plutôt que sur titre LIKE 'Voiture%' ? C'est le "LIKE" qui est pas terrible ?

    Au passage j'ai découvert sqlfiddle
    Question de normalisation de la base de données et performance de la requête.
    Dans l'ordre, du moins performant au plus performant :
    1 - titre LIKE '%Voiture%'
    2 - titre LIKE 'Voiture%',
    3 - type_evenement = 'Voiture',

    Avec un index posé sur le champ, l'égalité (=) est plus performante que le LIKE

  15. #15
    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
    Citation Envoyé par manzeki Voir le message
    Dans l'ordre, du moins performant au plus performant :
    1 - titre LIKE '%Voiture%'
    2 - titre LIKE 'Voiture%',
    3 - type_evenement = 'Voiture',
    Je rajouterai même :
    4 - UneColonneNumerique = 1

  16. #16
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    100
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 100
    Points : 64
    Points
    64
    Par défaut
    C'est bon ca a l'air de marcher au poil. J'ai donc rajouté une colonne numérique dans ma table cal_my_calendrieret mon script ressemble à ca :

    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
    foreach ($tableauCategories as $id_categorie) {
     
      $sqlMesEvents="
            SELECT 
            A.calendrier,
              A.date_debut AS debut,
             MIN(B.Date_Fin) AS fin 
            FROM   cal_my_events A
            INNER JOIN cal_my_events B
             ON B.date_debut <= A.Date_debut
            AND B.Date_fin >= A.Date_debut
            INNER JOIN cal_my_calendrier 
            ON A.calendrier = cal_my_calendrier.ID
            WHERE cal_my_calendrier.ressource=".$id_categorie."
            GROUP BY A.Date_debut
            HAVING COUNT(*) = (SELECT COUNT(*) FROM cal_my_calendrier WHERE ressource=".$id_categorie.")
       ";
    Les premiers essais ont l'air concluants.. Je m'en serais jamais sorti, j'avais jamais vu ce type de requête

    Donc merci beaucoup

  17. #17
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    100
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 100
    Points : 64
    Points
    64
    Par défaut
    Salut à tous,

    je fait un petit up de ce topic car à l'utilisation la requête telle qu'elle était écrite s'est vite mise à déconner. On est passé en prod, le nombre de calendriers et d'événements a grimpé, et la requête affichait des résultats farfelus. Je l'ai corrigée, alors je la poste ici si ca peut servir à d'autres :
    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
     
    foreach ($tableauCategories as $id_categorie) 
    {
     
    	$sqlMesEvents="
    	SELECT 
    	A.date_debut AS debut,
    	MIN(B.Date_Fin) AS fin
     
    	FROM  cal_my_events A 
     
    	INNER JOIN cal_my_events B
    	ON B.date_debut <= A.Date_debut
    	AND B.Date_fin >= A.Date_debut
     
    	INNER JOIN cal_my_calendrier C
    	ON A.calendrier = C.ID
     
    	INNER JOIN cal_my_calendrier D
    	ON  B.calendrier = D.ID
     
    	WHERE
    	C.ressource=".$id_categorie."
    	AND D.ressource=".$id_categorie."
     
    	GROUP BY A.Date_debut
     
    	HAVING COUNT(*) = (SELECT COUNT(*) FROM cal_my_calendrier WHERE ressource=".$id_categorie.")
       ";
        $reqMesEvents = $GLOBALS['bdd']->query($sqlMesEvents);

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

Discussions similaires

  1. Multi-selection dans une ComboBox ?
    Par Moloko dans le forum MFC
    Réponses: 5
    Dernier message: 07/07/2021, 17h26
  2. Trouvez des créneaux horaires disponibles
    Par css4ever dans le forum Langage
    Réponses: 9
    Dernier message: 17/08/2012, 15h36
  3. select count(*) plage horaire
    Par aziatedu13 dans le forum Langage SQL
    Réponses: 4
    Dernier message: 27/02/2012, 12h49
  4. Gestion de taches dans des créneaux horaires.
    Par ThomasAU dans le forum Débuter avec Java
    Réponses: 1
    Dernier message: 10/02/2010, 13h01
  5. faire un selection dans une image aves les APIs
    Par merahyazid dans le forum C++Builder
    Réponses: 3
    Dernier message: 30/04/2002, 10h44

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