【问题标题】:Oracle Pivot over Sequence of valuesOracle 透视值序列
【发布时间】:2020-07-02 21:20:55
【问题描述】:

我需要在一个可以取一百个值的列上旋转一个表,所以我更愿意简洁地定义可能值的范围,而不是逐个输入。似乎SEQUENCE 对象应该允许我指定这个范围,但我正在努力将它合并到PIVOT 语法中。

其次,我想将生成的透视列设置为以另一列为条件。

到目前为止我已经尝试过:

SELECT * FROM table
PIVOT
(
  COUNT(effect)
  FOR column
  IN VALUES(CREATE SEQUENCE my_seq
            INCREMENT BY 1
            START WITH 1
            MAXVALUE 100)
)

我的输入表看起来像这样,其中每个用户最多有 3 个 feature 值以及相应的 effect 增加(incr)或减少(decr):

user   column   effect
a      1        incr
a      5        decr
a      100      decr
b      1        decr
b      20       decr
b      40       decr
c      1        decr
c      5        incr
c      20       incr

当列具有增加/减少效果时,我想要的输出应该有 +1/-1,否则为 NULL:

user   column_1   column_5 ... column_20 ...
a      1          -1           NULL   
b      -1         NULL         -1
c      -1         1            1

--

编辑:
我意识到COUNT() 不会将列设置为+1/-1/NULL,但我只是想先解决SEQUENCE 问题。也许我应该只使用一组非常冗长的 CASE 语句,然后使用 PARTITION 将它们全部折叠到每个用户一行(见下文)?

WITH effects AS
(
SELECT
    user,
    CASE WHEN column = 1 THEN 
        CASE WHEN effect = 'incr' THEN 1
             WHEN effect = 'decr' THEN -1
             ELSE NULL
             END
        ELSE NULL
    END AS column_1
FROM
    table
)
SELECT
    user,
    MAX(column_1) OVER (PARTITION BY user) AS column_1
FROM
    effects

【问题讨论】:

    标签: oracle11g pivot pivot-table sequence


    【解决方案1】:

    一个序列是一个永久的数据库对象,你不能像那样动态地定义一个;即使使用序列,您也可以使用 nextval 来获取值。

    Oracle 必须知道查询在解析时将产生多少列,因此您无法在运行时确定多少列,而这正是您所尝试的。如果你真的不知道,那么你必须使用动态 SQL;或 XML 数据透视表,然后您必须将其解压缩。 From the documentation:

    XML 关键字允许pivot_in_clause 包含子查询或通配符关键字ANY。当pivot_in_clause 值事先未知时,子查询和ANY 通配符很有用。

    在这种情况下,使用另一个查询生成语句会更简单 - 无需键入所有值。您可以通过分层查询或递归 CTE 获得数字 1-100,然后可以使用listagg() 将它们组成一个值列表:

    with t (n) as (
      select 1 from dual
      union all
      select n + 1 from t where n < 100
    )
    select listagg(n, ', ') within group (order by n)
    from t;
    
    LISTAGG(N,',')WITHINGROUP(ORDERBYN)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100
    

    然后您可以将其用作构成整个查询的字符串的一部分:

    with t (n) as (
      select 1 from dual
      union all
      select n + 1 from t where n < 100
    )
    select q'^select *
    from your_table
    pivot (
      max(case effect when 'incr' then 1 when 'decr' then -1 end)
      for col in (^' || listagg(n, ', ') within group (order by n) || q'^)
    )
    order by usr^'
    from t;
    
    Q'^SELECT*FROMYOUR_TABLEPIVOT(MAX(CASEEFFECTWHEN'INCR'THEN1WHEN'DECR'THEN-1END)FORCOLIN(^'||LISTAGG(N,',')WITHINGROUP(ORDERBYN)||Q'^))ORDERBYUSR^'                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    select *
    from your_table
    pivot (
      max(case effect when 'incr' then 1 when 'decr' then -1 end)
      for col in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100)
    )
    order by usr
    

    然后运行生成的语句:

    select *
    from your_table
    pivot (
      max(case effect when 'incr' then 1 when 'decr' then -1 end)
      for col in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100)
    )
    order by usr;
    
    U          1          2          3          4          5          6          7          8          9         10         11         12         13         14         15         16         17         18         19         20         21         22         23         24         25         26         27         28         29         30         31         32         33         34         35         36         37         38         39         40         41         42         43         44         45         46         47         48         49         50         51         52         53         54         55         56         57         58         59         60         61         62         63         64         65         66         67         68         69         70         71         72         73         74         75         76         77         78         79         80         81         82         83         84         85         86         87         88         89         90         91         92         93         94         95         96         97         98         99        100
    - ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
    a          1                                          -1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   -1
    b         -1                                                                                                                                                                                                               -1                                                                                                                                                                                                                          -1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
    c         -1                                           1                                                                                                                                                                    1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
    

    当然,您可以将生成的语句作为动态 SQL 运行,但如果可以的话,复制和粘贴会更简单。


    您也可以更改此设置以使 CTE 仅提取表中实际存在的值:

    t (n) as (
      select distinct col from your_table
    )
    select q'^select *
    from your_table
    pivot (
      max(case effect when 'incr' then 1 when 'decr' then -1 end)
      for col in (^' || listagg(n, ', ') within group (order by n) || q'^)
    )
    order by usr^'
    from t;
    

    生成:

    select *
    from your_table
    pivot (
      max(case effect when 'incr' then 1 when 'decr' then -1 end)
      for col in (1, 5, 20, 40, 100)
    )
    order by usr
    

    在运行时会给出更易于管理的最终结果:

    U          1          5         20         40        100
    - ---------- ---------- ---------- ---------- ----------
    a          1         -1                               -1
    b         -1                    -1         -1           
    c         -1          1          1                      
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-21
      • 2022-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多