2010-01-11 4 views
1

Я работаю с SQLite.SQLite-запрос для присоединения к диапазону дат?

Предположим, у меня есть стол sales с двумя колонками, date и count, чтобы отслеживать, сколько очков из лимонада я продал в эту дату. Если я не буду продавать лимонад в определенный день, я слишком подавлен, чтобы создать новую строку в таблице sales.

Я хотел бы узнать среднее количество очков, проданных за определенный диапазон дат. Я мог бы выдать запрос, как это:

SELECT AVG(count) FROM sales WHERE date IS BETWEEN '2010-01-04' AND '2010-01-10'; 

Однако результат не будет точным, если все даты в этом диапазоне не включены в таблицу. Мне нужно каким-то образом сказать SQLite подсчитать недостающие строки как нули.

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

Как я уже говорил выше, я использую SQLite, поэтому вам не помогает, если вы порекомендуете мне другие базы данных. Тем не менее, если у вас есть больше опыта работы с другой базой данных и вы думаете, что ваше решение может быть выполнено в ванильном SQL, я бы хотел его услышать.

+0

можете ли вы что-нибудь сказать о диапазоне? должна ли она быть произвольной длиной? или есть максимум? –

ответ

5

Создать таблицу календаря и присоединиться на что:

Что-то, как это будет делать:

create table dates (id integer primary key); 
insert into dates default values; 
insert into dates default values; 
insert into dates select null from dates d1, dates d2, dates d3 , dates d4; 
insert into dates select null from dates d1, dates d2, dates d3 , dates d4; 
alter table dates add date datetime; 
update dates set date=date('2000-01-01',(-1+id)||' day'); 

Это будет охватывать вас до 2287-05-20 Добавление индекса в столбец даты в таблица дат не повредит. Мой sqlite немного ржавый, поэтому я предлагаю вам обратиться к the manual.

Edit: Код для индекса:

create unique index ux_dates_date on dates (date); 
+0

Это работает в sqlite.Умный хак. – benzado

3

Я думаю, что вам нужно что-то вроде этого:

SELECT sum(count)/((strftime('%s','2010-01-10')-strftime('%s','2010-01-04')+86400)/86400) 
FROM sales 
WHERE date IS BETWEEN '2010-01-04' AND '2010-01-10'; 

Запрос вычисляет точное количество дней, беря секунд между данными даты
и деление на 86400 (= 24 * 3600) сек.

Например

SELECT (strftime('%s','2010-03-01')-strftime('%s','2010-01-01') + 86400)/86400 

выходы 60 который является правильное значение.

Заканчивать SQLite-х Date And Time Functions.

+0

умный! Я думал о чем-то слишком сложном. –

+0

Это хорошо, но он работает только для вычисления среднего. У меня есть несколько более сложных вещей, которые я хочу делать там, где этого недостаточно. – benzado

1

Вы можете использовать Рекурсивное выражение Common Table для генерации серии дат и присоединиться к нему:

WITH RECURSIVE 
    cnt(x) AS (
    SELECT 0 
    UNION ALL 
    SELECT x+1 FROM cnt 
    LIMIT (SELECT ((julianday('2010-01-10') - julianday('2010-01-04'))) + 1) 
), 
WITH date_series AS (
    SELECT date(julianday('2010-01-04'), '+' || x || ' days') as date 
FROM date_series ds 
) 
SELECT AVG(COALESCE(s.count, 0)) as avg_sales_count 
FROM date_series ds 
    LEFT JOIN sales s ON ds.date = s.date 

Я написал сообщение в блоге с дополнительной информацией здесь: http://www.geekytidbits.com/generate-date-range-sqlite/

Смежные вопросы