J'ai sous MySQL des données représentant des actions horodatées attribuées à des utilisateurs, ce qui donne quelque chose comme ceci :
______________________________________
| Date | Individu |
| 2005-06-02 12:05:00 | Pierre |
| 2005-06-02 12:05:10 | Pierre |
| 2005-06-02 12:06:00 | Paul |
| 2005-06-02 12:10:00 | Jacques |
| 2005-06-02 12:11:30 | Jacques |
| 2005-06-02 12:20:00 | Pierre |
| 2005-06-02 12:30:00 | Jacques |
| .... | .... |
______________________________________
Je souhaiterais faire une sorte de GROUP BY qui s'appliquerait aux entrées consécutives, quelque chose comme un "SELECT MIN(Date), Individu FROM table GROUP BY CONSECUTIVE Individu" qui me renverrait pour chaque individu le début de son activité jusqu'à ce qu'un autre individu prenne la main :
______________________________________
| Min(Date) | Individu |
| 2005-06-02 12:05:00 | Pierre |
| 2005-06-02 12:06:00 | Paul |
| 2005-06-02 12:10:00 | Jacques |
| 2005-06-02 12:20:00 | Pierre |
| 2005-06-02 12:30:00 | Jacques |
| .... | .... |
______________________________________
Après fouille en règle de la doc MySQL et du Vaste Web, je ne trouve ni l'improbable commande (j'y croyais peu...) ni une astuce permettant de ruser finement pour obtenir ce résultat.
Un linuxfriens la connaîtrait-il, cette astuce ?
Un grand merci d'avance pour vos tuyaux !
# T'as droit à un langage de programmation pour faire ça ? :)
Posté par mac . Évalué à 1.
[^] # Re: T'as droit à un langage de programmation pour faire ça ? :)
Posté par JJD . Évalué à 2.
Je ne sais pas du tout comment faire ça avec une requête SQL, mais si tu exportes ta table dans un fichier (ou la sortie standard), c'est finalement assez simple à réaliser dans n'importe quel langage.
Un petit exemple : disons que tu as tes données triées par date dans un fichier "toto", un coup de
uniq -s27 toto
te donneras :
______________________________________
| Date | Individu |
| 2005-06-02 12:05:00 | Pierre |
| 2005-06-02 12:06:00 | Paul |
| 2005-06-02 12:10:00 | Jacques |
| 2005-06-02 12:20:00 | Pierre |
| 2005-06-02 12:30:00 | Jacques |
A+
JJD
[^] # Re: T'as droit à un langage de programmation pour faire ça ? :)
Posté par mouling . Évalué à 1.
# Distinct ?
Posté par wax . Évalué à 1.
[^] # Re: Distinct ?
Posté par mouling . Évalué à 1.
Je cherche à regrouper les entrées "qui se suivent" suivant un critère de tri quelconque (dans mon exemple, une date), tandis que le DISTINCT truc (ou le GROUP BY truc) me regroupe tous les "truc" de la table.
# User Defined Functions
Posté par ttt tt . Évalué à 2.
Par contre, tu peux surement te créer ta propre User Defined Function, en codant une bonne fois pour toute la fonction en C (par ex), et en l'intégrant au noyau MySQL, faut avoir accès à la compilation.
Un très bon bouquin sur MySQL t'expliquera comment faire ça.
(Voir MySQL 4 chez Micro Application, bon, ok c'est mon bouquin...)
Sinon, le manuel online explique comment faire, mais c'est pas les rois de la clarté.
L'avantage, c'est que une fois ta fonction implémentée, tu pourras t'en servir dans tes requettes.
[^] # Re: User Defined Functions
Posté par mouling . Évalué à 1.
Hum, c'est bien ce que je craignais...
tu peux surement te créer ta propre User Defined Function, en codant une bonne fois pour toute la fonction en C (par ex), et en l'intégrant au noyau MySQL
Ah, ça c'est une idée qu'elle est bonne et séduisante : tout à fait le genre de truc qui va m'amuser ! Je jetterai un coup d'oeil quand j'aurai un peu de temps, je suppose que ça ne va pas de soi.
Merci du tuyau !
# Hop
Posté par Pooly (site web personnel) . Évalué à 2.
Avec une table temporaire ou une subquery, ca passe pas ?
au pire poste sur la liste mysql ( mysql @ lists.mysql.com ) qui est tres efficace.
# Plusieurs colonnes dans le GROUP BY
Posté par Obsidian . Évalué à 1.
SELECT min(Date),individu FROM table GROUP BY Date,Individu
Ca ne marche pas ?
[^] # Re: Plusieurs colonnes dans le GROUP BY
Posté par Obsidian . Évalué à 2.
# Un des moyens,
Posté par Gyro Gearllose . Évalué à 3.
[^] # Re: Un des moyens,
Posté par mouling . Évalué à 1.
Qq tests plus tard, ça marche parfaitement en passant par une table temporaire, mais n'ai pas encore trouvé la requête qui va bien pour faire ça en une seule passe (grmmlml d'auto_increment qui veut pas passer dans un SELECT !). Je la poste dès que j'aurai trouvé...
[^] # CA MARCHE !
Posté par Obsidian . Évalué à 2.
Voici une commande qui marche en se passant des numéros d'incrémentation, qui ont ceci d'ennuyeux qu'ils brisent la requête si jamais on supprime une ligne :
select distinct min(b.heure),b.individu from pointage a join pointage b on b.heure > a.heure and a.individu != b.individu group by a.individu,a.heure order by 1
En considérant bien sûr que la table s'appelle « pointage » !
Seul inconvénient : Le premier gugusse à pointer n'apparaît jamais dans le résultat de cette requête ...
[^] # Re: CA MARCHE !
Posté par mouling . Évalué à 1.
[^] # Re: CA MARCHE !
Posté par Gyro Gearllose . Évalué à 2.
Si oui, ça peut peut-être te sortir d'affaire !
Tu utilises ta vue pour générer les tuples dans l'ordre des heures, avec l'auto-incrément, et tu te bases ensuite sur cette vue pour faire ta requête....
Bon, je ne sais pas trop quoi penser. Apparement, oui, mysql gère les vues (cf. http://dev.mysql.com/doc/mysql/fr/create-view.html).(...)
A toi de jouer, maintenant !
Ah, et puis, oui, je suis bien content de t'avoir aidé, car j'avais déjà rencontré un problème similmaire il y a quelques temps, mais à l'époque je n'avais pas réussi à le résoudre. Comme quoi....
[^] # Re: CA MARCHE !
Posté par Obsidian . Évalué à 2.
En plus, cela place ta requête en échec si une ligne est supprimée, car le pas de une unité entre chaque ligne n'est plus respecté.
De plus, ce n'est valable que si l'on insère les entrées chronologiquement. Si par exemple l'administrateur insère dans la table des informations provenant de deux sources distinctes et successive (qui a dit des fichiers Excel ?), tu es bon pour te taper une renumérotation manuelle de toutes tes entrées. Au pire, tu extrais le contenu de ta table avec un « SELECT ... ORDER BY heure; » vers un fichier, et tu fais un script qui te numérote tes lignes, mais le problème reste entier : Tu es obligé d'exporter le système de garantie de la cohérence de ta base en dehors du SGBD, tu ne peux plus assurer celle-ci en temps réel et, pire que tout, tu ne peux pas empêcher quelqu'un d'insérer des données corrompues entre deux contrôles.
Pas terrible.
[^] # Re: CA MARCHE !
Posté par Gyro Gearllose . Évalué à 2.
Je pense que c'est possible avec postgreSQL en plaçant une variable dans la vue. Comme c'est calculé à chaque fois que tu fais un select sur la vue, ça fonctionne forcément, aux erreurs près de ce que tu indiques dans ton post.
Quant au fait que ma requête n'est valable que si les entrées sont insérées chronologiquement, ceci peut éventuellement être réglé dans la définition de la vue, avec un order by des familles !
Sinon, et si c'est effectivement pour une application de pointage, j'en ai développé une à mon boulot, mais elle ne fonctionne pas du tout de cette manière.
A chacun sa façon de voir les choses !
[^] # Re: CA MARCHE !
Posté par mouling . Évalué à 1.
Cette commande a été ajoutée en MySQL 5.0.1.
et tant que la 5 sera en Development Release, pas question que je m'y risque !
Bon, soyons positifs : plus le temps passe, plus je cette échéance approche, et la résolution du problème itou !
[^] # Re: CA MARCHE !
Posté par Obsidian . Évalué à 2.
Solution propre pour parer à cette anomalie : Créer un index sur ta colonne « heure », qui sert ici de clé.
create index idx on pointage2 (heure);
En revanche, l'ajout du nom de l'utilisateur par ,b.individu ne peut pas fonctionner. C'est également un « bug » (pour autant que je sache, en tous cas), qui permet l'affichage de ce nom en même temps que la valeur issue d'une fonction d'agrégation.
Il faudrait transformer cette requête en sous-requête, et la passer à un ...
SELECT * FROM pointage WHERE heure in ([...]) ORDER BY heure ASC;
... pour que ce soit parfait, mais bizarrement, MySQL n'aime pas non plus mes sous-requêtes :-(
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.