Requête avec groupage par date un peut particulier

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Requête avec groupage par date un peut particulier

Re: Requête avec groupage par date un peut particulier

par bender » 10 oct. 2011, 20:11

Salut,

Et bien merci beaucoup pour ce coup de main, c'est exactement ce que je voulais faire. Effectivement, maintenant que je le vois ça parait beaucoup plus simple. Il faut que j'apprenne à poser les choses clairement sur le papier. J'ai tendance à vouloir coder à la volé en faisant mes schémas de tête mais j'ai pas encore le niveau pour ça.

Pour le premier poste il y a que 10 résultats car dans l'exemple je récupère que les réservations du 8/10/2011 sauf que j'ai fais une erreur sur la date de fin de la ligne 13 mais sinon c'est ça.

Je te remercie pour ton aide qui m'a été d'une grande utilité.

a+

Re: Requête avec groupage par date un peut particulier

par Cyrano » 09 oct. 2011, 18:25

Allez, un petit coup de pouce, c'est en somme assez simple.

Première chose, ta requête doit contenir une clause ORDER BY date_debut, date_fin pour pouvoir traiter ça sans t'arracher les cheveux.
Le résultat devrait ressembler à un tableau de ce style :
<?php
$aReservations = array(
    array(
        "id" => 5, "date_debut" => 1318050000, "date_fin" => 1318055400
    ),
    array(
        "id" => 1, "date_debut" => 1318055400, "date_fin" => 1318062600
    ),
    array(
        "id" => 7, "date_debut" => 1318055400, "date_fin" => 1318066200
    ),
    array(
        "id" => 2, "date_debut" => 1318057200, "date_fin" => 1318060800
    ),
    array(
        "id" => 4, "date_debut" => 1318059000, "date_fin" => 1318069800
    ),
    array(
        "id" => 6, "date_debut" => 1318064400, "date_fin" => 1318075200
    ),
    array(
        "id" => 11, "date_debut" => 1318068000, "date_fin" => 1318075200
    ),
    array(
        "id" => 9, "date_debut" => 1318078800, "date_fin" => 1318091400
    ),
    array(
        "id" => 13, "date_debut" => 1318080600, "date_fin" => 1318084200
    ),
    array(
        "id" => 8, "date_debut" => 1318080600, "date_fin" => 1318084200
    ),
    array(
        "id" => 12, "date_debut" => 1318086000, "date_fin" => 1318089600
    ),
    array(
        "id" => 3, "date_debut" => 1318091400, "date_fin" => 1318095000
    ),
    array(
        "id" => 10, "date_debut" => 1318096800, "date_fin" => 1318104000
    ),
    array(
        "id" => 14, "date_debut" => 1318096800, "date_fin" => 1318104000
    )
);
Le format timestamp est du coup très utile pour les comparaisons. Il va te falloir boucler sur ce tableau et définir à quel moment tu dois changer de groupe.

Il te faut donc des points de repères : un identifiant de ligne de groupe, et un repère de date de fin.

Suis bien le code ci-après basé sur le tableau montré plus haut, et lis bien chaque commentaire, il est important :
<?php
// ...
/**
 * On crée un tableau où on va stocker les identifiants par groupes;
 */
$aGroupes = array();
/**
 * Le tableau des groupes aura des index numériques, on fixe le premier à 1
 */
$grp_id    = 1;
/**
 * Un point de repère : la date de fin. Au départ, on l'établit à NULL puisqu'on a 
 * pas de valeur à y mettre.
 */
$grp_fin   = null;
/**
 * On boucle sur les résultats.
 * 
 * Ici, c'est une boucle foreach, mais dans la pratique, comme on utilise le retour
 * d'une requête SQL, il conviendra d'utiliser une boucle while.
 */
foreach($aReservations as $ligne)
{
    /**
     * Première chose : on vérifie si la date de fin est définie, sinon
     * on initialise notre point de repère.
     */
    if(is_null($grp_fin))
    {
        $grp_fin = $ligne['date_fin'];
    }
    /**
     * On vérifie si la date de début est supérieure ou égale à notre
     * point de repère de date de fin : si c'est le cas, alors on va 
     * changer de groupe.
     */
    if($ligne['date_debut'] >= $grp_fin)
    {
        /**
         * Comme on change de groupe, on peut trier le groupe juste avant.
         */
        // sort($aGroupes[$grp_id], SORT_NUMERIC);
        /**
         * On incrémente l'index pour passer au groupe suivant;
         */
        $grp_id ++;
        /**
         * On met à jour le point de repère de date de fin.
         */
        $grp_fin = $ligne['date_fin'];
    }
    /**
     * Si la date de fin est ultérieure à notre point de repère, alors
     * on met à jour le point de repère.
     */
    if($ligne['date_fin'] >= $grp_fin)
    {
        $grp_fin = $ligne['date_fin'];
    }
    /**
     * On ajoute l'identifiant dans le groupe déterminé ci-dessus.
     */
    $aGroupes[$grp_id][] = $ligne['id'];
}
/**
 * Terminé, on affiche le résultat pour vérifier.
 */
echo("<pre>\n");
var_dump($aGroupes);
echo("</pre>\n");
Et voilà ce que ça affiche :
array(5) {
  [1]=>
  array(1) {
    [0]=>
    string(1) "5"
  }
  [2]=>
  array(6) {
    [0]=>
    string(1) "1"
    [1]=>
    string(1) "2"
    [2]=>
    string(1) "4"
    [3]=>
    string(1) "6"
    [4]=>
    string(1) "7"
    [5]=>
    string(2) "11"
  }
  [3]=>
  array(4) {
    [0]=>
    string(1) "8"
    [1]=>
    string(1) "9"
    [2]=>
    string(2) "12"
    [3]=>
    string(2) "13"
  }
  [4]=>
  array(1) {
    [0]=>
    string(1) "3"
  }
  [5]=>
  array(2) {
    [0]=>
    string(2) "10"
    [1]=>
    string(2) "14"
  }
}
Si il y a un point qui t'échappe, reviens poser des questions :)

Re: Requête avec groupage par date un peut particulier

par Cyrano » 09 oct. 2011, 17:31

Salut, si on suit ton jeu d'essai, il semble qu'il manque des résultats dans ton regroupement, 4 pour être précis puisqu'il n'y a que 10 résultats sur les 14 entrées. Et je ne suis pas certain d'avoir bien saisi les critères de regroupement des différentes lignes... :-k

Mais bon, sauf erreur, ça devrait ressembler à ça si j'ai bien suivi :
+---------+-------------------+
| GROUPES | ID                |
+---------+-------------------+
|       1 | 5                 |
|       2 | 1, 2, 4, 6, 7, 11 |
|       3 | 9, 8, 12, 13      |
|       4 | 3                 |
|       5 | 10, 14            |
+---------+-------------------+
En SQL, tu ne pourras pas obtenir un résultat sous cette forme, il faut le faire par programmation.

Requête avec groupage par date un peut particulier

par bender » 09 oct. 2011, 16:09

Salut,

J'ai une table avec 3 colonnes : id, date_debut, date_fin. Les dates sont stockées au format timestamp unix. Je cherche à récupérer de manière groupé les id dont les horaires sont égaux ou superposés pour une journée précise par ordre de date_debut.

Exemple:

(dans mon exemple je n'utilise pas le format timestamp afin que ce soit compréhensible)

Image

* Il s'agit de réservations.

Je voudrais donc pouvoir récupérer les réservations pour le 8/10/2011 groupé de la manière suivante :

Image

A noter que dans le groupe2 par exemple, l'id 1 et 6 n'ont pas d'horaire superposé entre eux. Ils sont mis en relation par l'id 4. De même pour le groupe3, c'est l'id 9 qui met en relation l'id 8 et 12.

J'ai un niveau vraiment de base en sql qui me permet de récupérer les réservations du jour que je souhaite par ordre de "date_debut"(jusque là ça va lol), mais pour ce qui est du groupage, en particulier grouper les heures qui se superposent, je suis complètement largué. Si quelqu'un pouvait me filer un coup de main ou me mettre sur une piste ça me dépannerait bien. Est-ce qu'au moins c'est possible de faire ça avec sql ?

J'avoue qu'avant ça j'ai tenté de récupérer les réservations du jour avec mysql et puis de faire le groupage en php mais je me suis complètement emmêlé les pinceaux avec mes boucles et mes array dans tous les sens. C'est pourquoi je me suis dit qu'il serait peut être plus simple de tout récupérer directement comme il faut avec une requête mysql, mais je bloque aussi.

J'espère que mon post est compréhensible.

Merci d'avance

a+