【问题标题】:Complex SQL query with pivot使用数据透视的复杂 SQL 查询
【发布时间】:2015-04-08 04:54:44
【问题描述】:

我有下表。

数据表

R_id I_id 度量 CType 时间跨度 数量 日期 1 1 S C 第 100 周 2015 年 4 月 5 日 1 1 Q C 第 200 周 2015 年 4 月 5 日 1 1 I D 第 80 周 2015 年 4 月 5 日 1 2 S C 第 150 周 2015 年 4 月 5 日 1 2 Q C 第 100 周 2015 年 4 月 5 日 1 2 I D 第 50 周 2015 年 4 月 5 日
  • 指标可以有一组有限的值(S、Q、I..)
  • CType 将为 C、D 或 nil。
  • 时间跨度可以是每周/每天。
  • 日期将是每周的星期日(一周开始)和每日的当天日期。

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

  1. 如果 Timespan 为 Daily,请照原样复制上述指标的 Quantity。
  2. 将每周数量转换为每天 7 个数量。

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

    R_id I_id Date S Q I ...(其他 CType 不为 nil 的指标) 1 1 4/5/2015 30 60 80 ...(其他指标的数量) 1 1 2015 年 4 月 6 日 10 20 80 1 1 2015 年 4 月 7 日 10 20 80 1 1 2015 年 4 月 8 日 5 10 80 1 1 2015 年 4 月 9 日 10 20 80 1 1 2015 年 4 月 10 日 15 30 80 1 1 2015 年 4 月 11 日 20 40 80 1 2 2015 年 4 月 5 日 45 30 50 1 2 2015 年 4 月 6 日 15 10 50 1 2 2015 年 4 月 7 日 15 10 50 1 2 2015 年 4 月 8 日 7.5 5 50 1 2 2015 年 4 月 9 日 15 10 50 1 2 2015 年 4 月 10 日 22.5 15 50 1 2 2015 年 4 月 11 日 30 20 50

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

我们将不胜感激建议和指导。

【问题讨论】:

  • 更多样本数据和预期输出会很好。或者,更好的 sqlfiddle
  • @EatÅPeach - 希望这能更好地解释问题。

标签: sql view oracle11g pivot


【解决方案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

这将为每条记录生成 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 |

【讨论】:

    猜你喜欢
    • 2016-06-22
    • 1970-01-01
    • 1970-01-01
    • 2015-04-22
    • 1970-01-01
    • 2011-06-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多