2009-07-26 9 views
2

J'ai une table basée sur les événements que je voudrais produire une requête, par minute pour le nombre d'événements qui se produisaient.Comment générer une requête d'intervalle de temps dans SQLite?

Par exemple, j'ai une table d'événements comme:

CREATE TABLE events (
    session_id TEXT, 
    event  TEXT, 
    time_stamp DATETIME 
) 

Ce que j'ai transformé en le type de tableau suivant:

CREATE TABLE sessions (
    session_id TEXT, 
    start_ts  DATETIME, 
    end_ts  DATETIME, 
    duration  INTEGER 
); 

Maintenant, je veux créer une requête qui regrouperait la sessions par un comptage de ceux qui étaient actifs pendant une minute particulière. Où je reviendrais essentiellement quelque chose comme:

TIME_INTERVAL ACTIVE_SESSIONS 
------------- --------------- 
18:00   1 
18:01   5 
18:02   3 
18:03   0 
18:04   2 
+0

Quel est le sens de la « durée » si vous avez déjà « start_ts » et "end_ts"? – vog

+0

J'aurais pu l'omettre ... ce n'est pas germain à la question. Dans ma situation réelle, j'utilise un analogue de ceci pour éviter d'avoir à calculer la différence dans les requêtes quand on fait des requêtes sur la durée. – Kitson

+0

Ne serait-il pas préférable de calculer exactement les intervalles jusqu'au prochain changement? Les lignes ressembleraient à "18:00:32 | 18:04:17 | 1" et il serait beaucoup plus facile de calculer. Ce style d'information "start | end | count" faciliterait la création de graphiques, etc. – vog

Répondre

1

Ok, je pense que j'ai eu plus ce que je voulais. Cela ne tient pas compte des intervalles qui sont vides, mais c'est assez bon pour ce dont j'ai besoin.

select strftime('%Y-%m-%dT%H:%M:00.000',start_ts) TIME_INTERVAL, 
    (select count(session_id) 
     from sessions s2 
     where strftime('%Y-%m-%dT%H:%M:00.000',s1.start_ts) between s2.start_ts and s2.end_ts) ACTIVE_SESSIONS 
    from sessions s1 
    group by strftime('%Y-%m-%dT%H:%M:00.000',start_ts); 

Cela va générer une ligne par minute pour la période qui couvre les données avec un compte pour le nombre de sessions qui ont été avaient commencé (start_ts), mais n'a pas fini (end_ts).

1

PostgreSQL permet la requête suivante. Contrairement à votre exemple, cela renvoie une colonne supplémentaire pour le jour, et il omet les minutes où rien ne s'est passé (compte = 0).

select 
    day, hour, minute, count(*) 
from 
    (values (0),(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)) 
    as minutes (minute), 
    (values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9), 
      (10),(11),(12),(13),(14),(15),(16),(17),(18),(19), 
      (20),(21),(22),(23)) 
    as hours (hour), 
    (select distinct cast(start_ts as date) from sessions 
    union 
    select distinct cast(end_ts as date) from sessions) 
    as days (day), 
    sessions 
where 
    (day,hour,minute) 
    between (cast(start_ts as date),extract(hour from start_ts),extract(minute from start_ts)) 
     and (cast(end_ts as date), extract(hour from end_ts), extract(minute from end_ts)) 
group by 
    day, hour, minute 
order by 
    day, hour, minute;
+0

vous pouvez utiliser l'extension generate_series. plage (début, fin, étape) à la place de "valeurs (1), (2), ...": '.load generate_series.dll' ' SELECT heures.value, minute.value de generate_series (1, 59,1) comme minute; JOIN generate_series (1,24,1) en heures' – user2173403

1

Ce n'est pas exactement votre question, mais je pense que cela pourrait aider. Avez-vous regardé dans le SQLite R-Tree module? Cela vous permettra de créer un index virtuel sur le début/heure d'arrêt:

CREATE VIRTUAL TABLE sessions_index USING rtree (id, start, end); 

Ensuite, vous pouvez effectuer une recherche via:

SELECT * FROM sessions_index WHERE end >= <first minute> AND start <= <last minute>; 
Questions connexes