带有pivot的复杂SQL查询

时间:2015-04-08 04:54:44

标签: sql view oracle11g pivot

我有下表。

Data_table

R_id    I_id    Metric    CType    Timespan    Quantity    Date  
 1        1       S         C        Week         100     4/5/2015
 1        1       Q         C        Week         200     4/5/2015
 1        1       I         D        Week         80      4/5/2015
 1        2       S         C        Week         150     4/5/2015
 1        2       Q         C        Week         100     4/5/2015
 1        2       I         D        Week         50      4/5/2015 
  • 指标可以有一组有限的值(S,Q,I ..)
  • CType 将为C,D或nil。
  • Timespan 可以是每周/每日。
  • 日期将是每周的周日(周开始)以及每日的当天。

我的目标是将其转换为涉及

的日常视图
  1. 如果Timespan是每日,请按原样复制上述指标的数量。
  2. 将每周数量转换为7个每日数量。

    • 如果CType是D,则按原样复制数量。
    • 如果CType是C,则使用恒定百分比分解逻辑来分配每周超过7天。[30%,10%,10%,5%,10%,15%20%] = 100%
  3. 创建以下视图。

    R_id   I_id   Date     S    Q    I ... (other metrics whose CType is not nil)
      1     1    4/5/2015  30   60   80 ... (the quantity of the other metrics)
      1     1    4/6/2015  10   20   80
      1     1    4/7/2015  10   20   80
      1     1    4/8/2015   5   10   80
      1     1    4/9/2015  10   20   80
      1     1    4/10/2015 15   30   80
      1     1    4/11/2015 20   40   80
      1     2    4/5/2015  45   30   50
      1     2    4/6/2015  15   10   50
      1     2    4/7/2015  15   10   50
      1     2    4/8/2015  7.5   5   50
      1     2    4/9/2015  15   10   50
      1     2    4/10/2015 22.5 15   50
      1     2    4/11/2015 30   20   50
    
  4. 我可以写一堆java方法,它们将从上表中提取数据,并根据需要获取指标的值。但对于大型数据集,性能不会很好。数据库适用于此类数据计算。创建此视图后,我可以快速(并且简单地)查询它以获得我想要的内容。我可以编写简单的SQL查询。但我不知道如何开始解决这个问题!我可以在这里看到一个PIVOT(逻辑上,我不知道查询将如何甚至可以实现它)。但是如何从每周数量计算7个每日数量并将其放入VIEW?

    建议和指导将不胜感激。

1 个答案:

答案 0 :(得分:1)

您可以使用hierarchical次查询来生成每日数据。

SQL Fiddle

<强>查询

select 
    r_id,
    i_id,
    metric,
    ctype,
    timespan,
    quantity,
    tdate + level - 1   as m_tdate,
    level           as m_level,
    (case ctype
        when 'C' then
            (case level 
                when 1 then 0.3
                when 2 then 0.1
                when 3 then 0.1
                when 4 then 0.05
                when 5 then 0.1
                when 6 then 0.15
                when 7 then 0.2
            end)
        else 1
    end) * quantity     as m_quantity
from myt
where timespan = 'Week'
connect by level <= 7
and r_id = prior r_id
and i_id = prior i_id
and metric = prior metric
and ctype = prior ctype
and timespan = prior timespan
and prior sys_guid() is not null

这将为每条记录生成七天数据

<强> Results

| R_ID | I_ID | METRIC | CTYPE | TIMESPAN | QUANTITY |               M_TDATE | M_LEVEL | M_QUANTITY |
|------|------|--------|-------|----------|----------|-----------------------|---------|------------|
|    1 |    1 |      I |     D |     Week |       80 | May, 04 2015 00:00:00 |       1 |         80 |
|    1 |    1 |      I |     D |     Week |       80 | May, 05 2015 00:00:00 |       2 |         80 |
|    1 |    1 |      I |     D |     Week |       80 | May, 06 2015 00:00:00 |       3 |         80 |
|    1 |    1 |      I |     D |     Week |       80 | May, 07 2015 00:00:00 |       4 |         80 |
|    1 |    1 |      I |     D |     Week |       80 | May, 08 2015 00:00:00 |       5 |         80 |
|    1 |    1 |      I |     D |     Week |       80 | May, 09 2015 00:00:00 |       6 |         80 |
|    1 |    1 |      I |     D |     Week |       80 | May, 10 2015 00:00:00 |       7 |         80 |
|    1 |    1 |      Q |     C |     Week |      200 | May, 04 2015 00:00:00 |       1 |         60 |
|    1 |    1 |      Q |     C |     Week |      200 | May, 05 2015 00:00:00 |       2 |         20 |
|    1 |    1 |      Q |     C |     Week |      200 | May, 06 2015 00:00:00 |       3 |         20 |
|    1 |    1 |      Q |     C |     Week |      200 | May, 07 2015 00:00:00 |       4 |         10 |
|    1 |    1 |      Q |     C |     Week |      200 | May, 08 2015 00:00:00 |       5 |         20 |
|    1 |    1 |      Q |     C |     Week |      200 | May, 09 2015 00:00:00 |       6 |         30 |
|    1 |    1 |      Q |     C |     Week |      200 | May, 10 2015 00:00:00 |       7 |         40 |
|    1 |    1 |      S |     C |     Week |      100 | May, 04 2015 00:00:00 |       1 |         30 |
|    1 |    1 |      S |     C |     Week |      100 | May, 05 2015 00:00:00 |       2 |         10 |
|    1 |    1 |      S |     C |     Week |      100 | May, 06 2015 00:00:00 |       3 |         10 |
|    1 |    1 |      S |     C |     Week |      100 | May, 07 2015 00:00:00 |       4 |          5 |
|    1 |    1 |      S |     C |     Week |      100 | May, 08 2015 00:00:00 |       5 |         10 |
|    1 |    1 |      S |     C |     Week |      100 | May, 09 2015 00:00:00 |       6 |         15 |
|    1 |    1 |      S |     C |     Week |      100 | May, 10 2015 00:00:00 |       7 |         20 |
|    1 |    2 |      I |     D |     Week |       50 | May, 04 2015 00:00:00 |       1 |         50 |
|    1 |    2 |      I |     D |     Week |       50 | May, 05 2015 00:00:00 |       2 |         50 |
|    1 |    2 |      I |     D |     Week |       50 | May, 06 2015 00:00:00 |       3 |         50 |
|    1 |    2 |      I |     D |     Week |       50 | May, 07 2015 00:00:00 |       4 |         50 |
|    1 |    2 |      I |     D |     Week |       50 | May, 08 2015 00:00:00 |       5 |         50 |
|    1 |    2 |      I |     D |     Week |       50 | May, 09 2015 00:00:00 |       6 |         50 |
|    1 |    2 |      I |     D |     Week |       50 | May, 10 2015 00:00:00 |       7 |         50 |
|    1 |    2 |      Q |     C |     Week |      100 | May, 04 2015 00:00:00 |       1 |         30 |
|    1 |    2 |      Q |     C |     Week |      100 | May, 05 2015 00:00:00 |       2 |         10 |
|    1 |    2 |      Q |     C |     Week |      100 | May, 06 2015 00:00:00 |       3 |         10 |
|    1 |    2 |      Q |     C |     Week |      100 | May, 07 2015 00:00:00 |       4 |          5 |
|    1 |    2 |      Q |     C |     Week |      100 | May, 08 2015 00:00:00 |       5 |         10 |
|    1 |    2 |      Q |     C |     Week |      100 | May, 09 2015 00:00:00 |       6 |         15 |
|    1 |    2 |      Q |     C |     Week |      100 | May, 10 2015 00:00:00 |       7 |         20 |
|    1 |    2 |      S |     C |     Week |      150 | May, 04 2015 00:00:00 |       1 |         45 |
|    1 |    2 |      S |     C |     Week |      150 | May, 05 2015 00:00:00 |       2 |         15 |
|    1 |    2 |      S |     C |     Week |      150 | May, 06 2015 00:00:00 |       3 |         15 |
|    1 |    2 |      S |     C |     Week |      150 | May, 07 2015 00:00:00 |       4 |        7.5 |
|    1 |    2 |      S |     C |     Week |      150 | May, 08 2015 00:00:00 |       5 |         15 |
|    1 |    2 |      S |     C |     Week |      150 | May, 09 2015 00:00:00 |       6 |       22.5 |
|    1 |    2 |      S |     C |     Week |      150 | May, 10 2015 00:00:00 |       7 |         30 |

一旦你有了这个,你需要转动结果,这可以通过简单的GROUP BY

来完成

<强>查询

with x as (
        select 
            r_id,
            i_id,
            metric,
            ctype,
            timespan,
            quantity,
            tdate + level - 1   as m_tdate,
            level           as m_level,
            (case ctype
                when 'C' then
                    (case level 
                        when 1 then 0.3
                        when 2 then 0.1
                        when 3 then 0.1
                        when 4 then 0.05
                        when 5 then 0.1
                        when 6 then 0.15
                        when 7 then 0.2
                    end)
                else 1
            end) * quantity     as m_quantity
        from myt
        where timespan = 'Week'
        connect by level <= 7
        and r_id = prior r_id
        and i_id = prior i_id
        and metric = prior metric
        and ctype = prior ctype
        and timespan = prior timespan
        and prior sys_guid() is not null
            UNION ALL
    select
            r_id,
            i_id,
            metric,
            ctype,
            timespan,
            quantity,
            tdate           as m_tdate,
            1           as m_level,
            quantity        as m_quantity
        from myt
        where timespan = 'Day'
)
select
    r_id,
    i_id,
    m_tdate,
    sum(case when metric = 'S' then m_quantity end) S,
    sum(case when metric = 'Q' then m_quantity end) Q,
    sum(case when metric = 'I' then m_quantity end) I
from x
group by 
    r_id,
    i_id,
    m_tdate
order by 
    r_id,
    i_id,
    m_tdate

<强> Results

| R_ID | I_ID |                 M_TDATE |      S |      Q |   I |
|------|------|-------------------------|--------|--------|-----|
|    1 |    1 |   May, 04 2015 00:00:00 |     30 |     60 |  80 |
|    1 |    1 |   May, 05 2015 00:00:00 |     10 |     20 |  80 |
|    1 |    1 |   May, 06 2015 00:00:00 |     10 |     20 |  80 |
|    1 |    1 |   May, 07 2015 00:00:00 |      5 |     10 |  80 |
|    1 |    1 |   May, 08 2015 00:00:00 |     10 |     20 |  80 |
|    1 |    1 |   May, 09 2015 00:00:00 |     15 |     30 |  80 |
|    1 |    1 |   May, 10 2015 00:00:00 |     20 |     40 |  80 |
|    1 |    2 | April, 03 2015 00:00:00 | (null) | (null) | 120 |
|    1 |    2 |   May, 04 2015 00:00:00 |     45 |     30 |  50 |
|    1 |    2 |   May, 05 2015 00:00:00 |     15 |     10 |  50 |
|    1 |    2 |   May, 06 2015 00:00:00 |     15 |     10 |  50 |
|    1 |    2 |   May, 07 2015 00:00:00 |    7.5 |      5 |  50 |
|    1 |    2 |   May, 08 2015 00:00:00 |     15 |     10 |  50 |
|    1 |    2 |   May, 09 2015 00:00:00 |   22.5 |     15 |  50 |
|    1 |    2 |   May, 10 2015 00:00:00 |     30 |     20 |  50 |