2010-05-26 3 views
3

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

В целях простоты я представлю очень упрощенные (почти тривиализированные) версии таблиц, которые я использую здесь. Таблица данных продаж является видом и имеет следующую структуру:

CREATE TABLE sales_data (
    sales_time date NOT NULL, 
    sales_amt double NOT NULL 
) 

Для этого вопроса. Я оставил другие поля, которые вы ожидаете увидеть - например product_id, sales_person_id и т. Д. И т. Д., Поскольку они не имеют прямого отношения к этому вопросу. AFAICT, единственными полями, которые будут использоваться в запросе, являются поля sales_time и sales_amt (если только я не ошибаюсь).

У меня также есть дата размер таблица со следующей структурой:

CREATE TABLE date_dimension (
    id integer NOT NULL, 
    datestamp date NOT NULL, 
    day_part integer NOT NULL, 
    week_part integer NOT NULL, 
    month_part integer NOT NULL, 
    qtr_part integer NOT NULL, 
    year_part integer NOT NULL, 
); 

, какой раздел даты в диапазоне отчетности.

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

  1. Верните изменения в недели на неделю sales_amt в течение определенного периода времени. Например, изменение между продажами сегодня и продажами N дней назад - где N - положительное целое число (N = 7 в этом случае).

  2. возвращение изменение на изменение sales_amt на указанный период. Ибо в (1). мы подсчитали недельную неделю. Теперь мы хотим знать, как это изменение отличается от (неделя за неделю), рассчитанная на прошлой неделе.

Я застрял, однако, на этом этапе, поскольку SQL - это мое самое слабое умение. Я был бы признателен, если бы мастер SQL мог объяснить, как я могу писать эти запросы агрегированным DB (то есть с использованием ANSI SQL).

+0

Это поможет, если вы разместите подробный ERD. Ваш стол фактов кажется немного необычным. Что такое строка в таблице фактов? Одна транзакция или какая-то кумулятивная ценность? Предположим, мы продаем один шоколадный бар в 2 часа дня за 2 доллара и еще один в 3 часа дня за 2 доллара - каково изменение в продажах, которое должно означать? –

ответ

5

Как уже отмечалось выше, я, вероятно, не понимаю вашу модель, поэтому он re - простой, чтобы начать.

dim4_model_01_1

Теперь, если я хочу каждую неделю продаж за календарный 2010 год

select 
    CalendarYearWeek 
    , sum(SalesAmount) 
from factSales as f 
join dimDate as d on d.DateKey = f.DateKey 
where Year = 2010 
group by CalendarYearWeek 

CalendarYearWeek столбец в dimDate, VARCHAR (8), например, '2010-W03', Year является целочисленный столбец в dimDate тоже.

Не уверен, что это близко к тому, что вы искали, но может быть началом.

EDIT

dimDate также имеет следующие столбцы:

WeekNumberInEpoch, целое число - увеличивается увеличивается, начиная с некоторого момента эпохи в прошлом. Все строки в dimDate в течение той же недели имеют один и тот же WeekNumberInEpoch.

DayOfWeek, VARCHAR (10) - 'воскресенье', 'понедельник', ...

DayNumberInWeek, целое число - 1-7

Это использует КТР, должны работать с последние PostgreSQL, SQL Server, Oracle, DB2. Для других вы можете упаковать CTE (q_00) в подзапрос.

-- for week to previous week 
with 
q_00 as (
    select 
     WeekNumberInEpoch 
     , sum(SalesAmount) as Amount 
    from factSale as f 
    join dimDate as d on d.DateKey = f.DateKey 
    where CalendarYear = 2010 
    group by WeekNumberInEpoch 
) 
select 
    a.WeekNumberInEpoch 
    , a.Amount as ThisWeekSales 
    , b.Amount as LastWeekSales 
    , a.Amount - b.Amount as Difference 
from q_00 as a 
join q_00 as b on b.WeekNumberInEpoch = a.WeekNumberInEpoch - 1 
order by a.WeekNumberInEpoch desc ; 


-- for day of week to day of previous week 
-- monday to monday, tuesday to tuesday, ... 
with 
q_00 as (
    select 
     WeekNumberInEpoch 
     , DayOfWeek 
     , sum(SalesAmount) as Amount 
    from factSale as f 
    join dimDate as d on d.DateKey = f.DateKey 
    where CalendarYear = 2010 
    group by WeekNumberInEpoch, DayOfWeek 
) 
select 
    a.WeekNumberInEpoch 
    , a.DayOfWeek 
    , a.Amount as ThisWeekSales 
    , b.Amount as LastWeekSales 
    , a.Amount - b.Amount as Difference 
from q_00 as a 
join q_00 as b on (b.WeekNumberInEpoch = a.WeekNumberInEpoch - 1 
        and b.DayOfWeek = a.DayOfWeek) 
order by a.WeekNumberInEpoch desc, a.DayOfWeek ; 



-- Sliding by day and day difference (= 7) 
with 
q_00 as (
    select 
     DayNumberInEpoch 
     , FullDate 
     , DayOfWeek 
     , sum(SalesAmount) as Amount 
    from factSale as f 
    join dimDate as d on d.DateKey = f.DateKey 
    where CalendarYear = 2010 
    group by DayNumberInEpoch, FullDate, DayOfWeek 
) 
select 
    a.FullDate as ThisDay 
    , a.DayOfWeek as ThisDayName 
    , a.Amount as ThisDaySales 
    , b.FullDate as PreviousPeriodDay 
    , b.DayOfWeek as PreviousDayName 
    , b.Amount as PreviousPeriodDaySales 
    , a.Amount - b.Amount as Difference 
from q_00 as a 
join q_00 as b on b.DayNumberInEpoch = a.DayNumberInEpoch - 7 
order by a.FullDate desc ; 
+0

@damir: +1 для красивой ERD. Я не знаю, как ты это сделал. Я предполагаю, что я, возможно, не изложил свою проблему правильно. Тем не менее, ERD, который вы предоставили, почти точно соответствует моему db - и я замечаю, что единственными таблицами, используемыми в запросе, были таблица фактов и таблица dimDate - вот почему все они были включены в мой вопрос. Запрос, который вы предоставили, определенно находится на правильном пути - по крайней мере, он показывает, как извлекать данные из таблицы фактов на основе таблицы размеров даты. Следующий (и окончательный) шаг - это как запросить базу данных, скажем еженедельные или ежемесячные изменения в объеме продаж. – morpheous

+0

@damir: И, наконец, его неделя на неделе меняет то, что я хочу. Предоставленный вами фрагмент запроса показывает кумулятивную (т. Е. Сумму) за период. То, что я хочу рассчитать (например), - это изменение между продажами сегодня и продажами N дней назад - где N - положительное целое число (N = 7 в этом случае). Надеюсь, это разъяснит, что я пытаюсь сделать. mtia – morpheous

+0

@damir: похоже, это именно то, что я хочу делать (судя по вашим комментариям). Мне просто нужно прочитать (и перечитать SQL, чтобы это полностью понять), например, я не уверен, почему q_00 использует сумму). Как только я проверил его на своем дБ, и он работает, я буду принимать это как окончательный ответ, а если нет, я вернусь с некоторыми вопросами. спасибо – morpheous

2

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

ваших запросов для (1.) и (2) может быть построен таким образом.

Да, большинство SQL диалектов позволяют infering этой информации времени/дате функции .. но они медленно (-er) и сложнее, чем использование таблицы размеров.

+0

благодарит за комментарий. Не могли бы вы подробнее рассказать? - возможно, с примером. Я не уверен, что я точно понимаю, что вы имеете в виду, или действительно, как его реализовать. – morpheous

+0

@morpheous: вы задаете два вопроса (или, может быть, я расширил его до двух): (1) какой DB/data design использовать (2) как запросить данные. Поскольку ваша таблица sales_data очень ограничена (нет идентификатора пользователя, contractID, ProductID), я предполагаю, что вы находитесь на этапе мозгового штурма дизайна? – lexu

+0

+1 для указания таблицы размеров даты. Я обновил свой вопрос в свете ваших комментариев. – morpheous