如何使用ANSI SQL为简单的数据仓库编写这两个查询?

mor*_*ous 3 sql data-warehouse ansi-sql

我正在编写一个简单的数据仓库,它允许我查询表以观察数据的周期性(比如每周)变化,以及数据变化的变化(例如每周销售额的每周变化).

为了简单起见,我将介绍我在这里使用的表的非常简化(几乎无关紧要)的版本.销售数据表是一个视图,具有以下结构:

CREATE TABLE sales_data (
     sales_time date NOT NULL,
     sales_amt double NOT NULL
)
Run Code Online (Sandbox Code Playgroud)

出于这个问题的目的.我遗漏了你期望看到的其他字段 - 比如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, 
);
Run Code Online (Sandbox Code Playgroud)

哪个分区的日期为报告范围.

我需要编写允许我执行以下操作的查询:

  1. 在指定时间段内返回sales_amt 更改.例如,今天销售与销售N天之间的变化 - 其中N是正整数(在这种情况下N == 7).

  2. 返回指定期间sales_amt 变化的变化.对于(1).我们计算了一周的变化.现在我们想知道这种变化与上周计算的(周和周)变化有何不同.

然而,我在这一点上陷入困​​境,因为SQL是我最弱的技能.如果SQL主管可以解释如何以DB不可知的方式编写这些查询(即使用ANSI SQL),我将不胜感激.

Dam*_*vic 5

如上面的评论中所述,我可能不了解您的模型 - 所以这是一个简单的入门.

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
Run Code Online (Sandbox Code Playgroud)

CalendarYearWeek是dimDate中的列,varchar(8),例如'2010-w03',Year也是dimDate 中的整数列.

不确定这是否接近您所寻找的,但可能是一个开始.

编辑

dimDate也有以下列:

WeekNumberInEpoch,整数 - 从过去的某个纪元日期开始增加.同一周内dimDate中的所有行都具有相同的WeekNumberInEpoch.

DayOfWeek,varchar(10) - 'sunday','monday',...

DayNumberInWeek,整数 - 1-7

这使用CTE,应该与最新的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 ;
Run Code Online (Sandbox Code Playgroud)