SQLite запрос присоединиться к диапазону дат? - PullRequest
1 голос
/ 12 января 2010

Я работаю с SQLite.

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

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

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

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

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

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

Ответы [ 3 ]

6 голосов
/ 12 января 2010

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

Что-то вроде этого подойдет:

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 немного ржавый, поэтому я советую вам инструкцию .

Редактировать: Код индекса:

create unique index ux_dates_date on dates (date);
3 голосов
/ 12 января 2010

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

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.

1 голос
/ 07 апреля 2016

Вы можете использовать выражение Recursive 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/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...