2009-05-13 4 views
1

У меня есть приложение Python. Он имеет базу данных SQLite, полную данных о вещах, которые происходят, извлекаемые веб-скребком из Интернета. Эти данные включают в себя группы времени-времени, такие как временные метки Unix, в столбце, зарезервированном для них. Я хочу получить имена организаций, которые делали что-то, и подсчитывать, как часто они их делали, но делать это каждую неделю (т. Е. 604 800 секунд). У меня есть данные.Как сделать GROUP BY на каждом заданном приращении значения поля?

псевдокод:

for each 604800-second increment in time: 
select count(time), org from table group by org 

По сути то, что я пытаюсь сделать, это итерацию через базу данных, как список, отсортированный по столбцу времени, с значением шага 604800. Цель состоит в том, чтобы проанализировать, как распределение из разных организаций в целом изменились с течением времени.

Если это вообще возможно, я бы хотел избежать вытягивания всех строк из db и обработки их в Python, поскольку это кажется a) неэффективным и b), вероятно, бессмысленным, учитывая, что данные находятся в базе данных.

ответ

1

Не будучи знаком с SQLite Я думаю, что этот подход должен работать для большинства баз данных, так как она находит НомерНедели и вычитает смещение

SELECT org, ROUND(time/604800) - week_offset, COUNT(*) 
FROM table 
GROUP BY org, ROUND(time/604800) - week_offset 

В Oracle я хотел бы использовать следующее, если время было колонка даты:

SELECT org, TO_CHAR(time, 'YYYY-IW'), COUNT(*) 
FROM table 
GROUP BY org, TO_CHAR(time, 'YYYY-IW') 

SQLite, вероятно, имеет аналогичную функциональность, которая позволяет использовать этот вид SELECT, который проще на глазу.

+0

Да, вы можете использовать функцию strftime для форматирования строки даты и времени (и модификатора unixepoch, если это то, с чего вы начинаете), а также более простой подход, основанный на усечении номера unix-epoch. –

+0

Спасибо! это решение; TO_CHAR не существует в sqlite, но функции strftime делают, и я смог сортировать его таким образом. – user106514

1

Создайте таблицу, в которой перечислены все недели с эпохи, и JOIN это ваша таблица событий.

CREATE TABLE Weeks (
    week INTEGER PRIMARY KEY 
); 

INSERT INTO Weeks (week) VALUES (200919); -- e.g. this week 

SELECT w.week, e.org, COUNT(*) 
FROM Events e JOIN Weeks w ON (w.week = strftime('%Y%W', e.time)) 
GROUP BY w.week, e.org; 

Существует только 52-53 недели в год. Даже если вы заселяете таблицу Weeks в течение 100 лет, это все еще небольшой стол.

1

Чтобы сделать это в соответствии с настройками (что хорошо подходит SQL), вам потребуется представление ваших временных приращений на основе набора. Это может быть временная таблица, постоянная таблица или производная таблица (т. Е. Подзапрос). Я не очень хорошо разбираюсь в SQLite, и прошло некоторое время с тех пор, как я работал с UNIX. Временные метки в UNIX - это всего лишь # секунд с некоторой установленной даты/времени? Используя стандартный календарь таблицы (что полезно иметь в базе данных) ...

SELECT 
    C1.start_time, 
    C2.end_time, 
    T.org, 
    COUNT(time) 
FROM 
    Calendar C1 
INNER JOIN Calendar C2 ON 
    C2.start_time = DATEADD(dy, 6, C1.start_time) 
INNER JOIN My_Table T ON 
    T.time BETWEEN C1.start_time AND C2.end_time -- You'll need to convert to timestamp here 
WHERE 
    DATEPART(dw, C1.start_time) = 1 AND -- Basically, only get dates that are a Sunday or whatever other day starts your intervals 
    C1.start_time BETWEEN @start_range_date AND @end_range_date -- Period for which you're running the report 
GROUP BY 
    C1.start_time, 
    C2.end_time, 
    T.org 

таблица Календарь может принимать любые формы вы хотите, чтобы вы могли использовать UNIX метки времени в нем для start_time и END_TIME. Вы просто предварительно заполняете его всеми датами в любом возможном диапазоне, который вы, возможно, захотите использовать. Даже переход с 1900-01-01 до 9999-12-31 не будет ужасно большим столом. Это может пригодиться для большого количества запросов типа отчетности.

Наконец, этот код является T-SQL, поэтому вам, вероятно, потребуется преобразовать DATEPART и DATEADD в любой эквивалент SQLite.