Désolé, le titre de la question est un peu vague, alors voici un exemple pratique.Comment regrouper, placer et filtrer un ensemble de résultats pour un ensemble de données très volumineux
J'ai une table dans laquelle chaque utilisateur (userid) obtient une valeur tous les quelques jours. Je veux trouver la dernière de ces valeurs pour chaque utilisateur, ventilée par mois, et compter leur nombre dans une fourchette.
Voici un exemple de tableau et des données représentatives:
CREATE TABLE `datasource` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`userId` INT UNSIGNED NOT NULL ,
`unixts` INT UNSIGNED NOT NULL ,
`value` INT UNSIGNED NOT NULL ,
INDEX (`userId`)
);
INSERT INTO `datasource`
(`userId`, `unixts`, `value`)
VALUES
(1, UNIX_TIMESTAMP('2010-07-01'), 500),
(1, UNIX_TIMESTAMP('2010-07-15'), 610),
(1, UNIX_TIMESTAMP('2010-08-02'), 740),
(2, UNIX_TIMESTAMP('2010-07-03'), 506),
(2, UNIX_TIMESTAMP('2010-07-18'), 640),
(2, UNIX_TIMESTAMP('2010-08-09'), 340),
(3, UNIX_TIMESTAMP('2010-07-03'), 506),
(3, UNIX_TIMESTAMP('2010-08-18'), 640)
;
Maintenant, voici une requête pour obtenir ce que je suis après:
select
month(FROM_UNIXTIME(unixts)) as month,
sum(if(value >= 700, 1, 0)) as '700 and up',
sum(if(value BETWEEN 600 AND 699, 1, 0)) as '600-699',
sum(if(value BETWEEN 500 AND 599, 1, 0)) as '500-599',
sum(if(value <= 499, 1, 0)) as '499 and below',
count(*) as total
from
datasource
where
id in (
select
max(id)
from
datasource
where
unixts between UNIX_TIMESTAMP('2010-07-01') and UNIX_TIMESTAMP('2010-09-01')
group by
userId, month(from_unixtime(unixts))
)
group by
month(FROM_UNIXTIME(unixts));
+-------+------------+---------+---------+---------------+-------+
| month | 700 and up | 600-699 | 500-599 | 499 and below | total |
+-------+------------+---------+---------+---------------+-------+
| 7 | 0 | 2 | 1 | 0 | 3 |
| 8 | 1 | 1 | 0 | 1 | 3 |
+-------+------------+---------+---------+---------------+-------+
Cette requête fonctionne très bien pour notre petit jeu de résultats. Toutefois, si vous lancez 44 millions de lignes dans la table de sources de données, il s'interrompt.
Existe-t-il un moyen optimisé pour écrire cette requête qui peut accomplir ce que je veux sans arrimer mysql pendant plusieurs jours?