带数据透视表的复杂 SQL 查询

Complex SQL query with pivot

我有以下 table.

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 

我的目标是将其转换为每日视图,其中涉及

  1. 如果时间跨度是每天,请按原样复制上述指标的数量。
  2. 将每周数量转换为 7 每天数量。

    • 如果 CType 是 D,请按原样复制数量。
    • 如果 CType 是 C,则使用恒定百分比细分逻辑将每周分配给 7 days.eg [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
    

我可以编写一堆 java 方法,这些方法将从上面 table 中提取数据并根据需要获取指标值。但是对于大数据集,性能不会很好。数据库就是为这种类型的数据计算而设计的。创建此视图后,我可以快速(简单地)查询它以获得我想要的内容。我可以编写简单的 sql 查询。但我不知道如何开始解决这个问题!我可以在这里看到一个 PIVOT(从逻辑上讲,我不知道查询将如何甚至可以实现它)。但是如何从每周数量计算出7天数量并将其放入VIEW中?

建议和指导将不胜感激。

您可以使用 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

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

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 |