【问题标题】:Using DENSE_RANK() to pull data into columns from rows使用 DENSE_RANK() 将数据从行中提取到列中
【发布时间】:2021-02-04 14:58:08
【问题描述】:

我希望使用 SQL (Oracle) 通过评估特定 ID 上的日期来将数据从行中提取到列中。以下是我的数据目前的样子:

|    ID    |   Date   |   Price   |
-----------------------------------
|   1234   |10/1/2020 |  $12.96   |
|   1234   |10/1/2021 |  $11.32   |
|   1234   |10/1/2022 |  $10.01   |
|   5678   | 6/1/2020 |  $59.96   |

期望的输出:

|    ID    |Yr1 Price |Yr2 Price |Yr3 Price |
---------------------------------------------
|   1234   |  $12.96  |  $11.32  |  $10.01  |
|   5678   |  $59.96  |          |          |

我尝试了几种不同的方法,但都没有成功。我相信 DENSE_RANK() 函数可能是最好的,但会给出一个错误,即它是一个窗口函数并且不允许在那里。所以我遇到了障碍,不确定如何进行。我当前的 SQL 代码是:

 select id, 
       (select price from price_tbl where DENSE_RANK() Over (partition by id) = 1) as yr_1,
       (select price from price_tbl where DENSE_RANK() Over (partition by id) = 2) as yr_2,
       (select price from price_tbl where DENSE_RANK() Over (partition by id) = 3) as yr_3
    from master_tbl

非常感谢任何帮助!

【问题讨论】:

    标签: sql oracle oracle11g pivot oracle-sqldeveloper


    【解决方案1】:

    通过创建包含条件聚合的函数(例如

    CREATE OR REPLACE FUNCTION Get_Prices RETURN SYS_REFCURSOR IS
      v_recordset SYS_REFCURSOR;
      v_sql       VARCHAR2(32767);
      v_str       VARCHAR2(32767);
    BEGIN
      SELECT LISTAGG( 'MAX(CASE WHEN rn = '||rn||' THEN Price END) AS "Price '||rn||'"' , ',' ) 
              WITHIN GROUP ( ORDER BY 1 )
        INTO v_str
        FROM ( SELECT DISTINCT ROW_NUMBER() OVER (PARTITION BY id ORDER BY 0) AS rn
                 FROM master_tbl ); 
    
      v_sql :=
      'SELECT ID, '|| v_str ||'
         FROM (SELECT p.*,
                      ROW_NUMBER() OVER (PARTITION BY id ORDER BY "Date") AS rn
                 FROM master_tbl m )
        GROUP BY id';
    
      OPEN v_recordset FOR v_sql;
      DBMS_OUTPUT.PUT_LINE(v_sql);
      RETURN v_recordset;
    END;
    /
    

    然后从 SQL Developer 的命令行调用

    VAR rc REFCURSOR
    EXEC :rc := Get_Prices;
    PRINT rc
    

    【讨论】:

      【解决方案2】:

      您可以使用row_number() 和条件聚合:

      select id, 
             max(case when seqnum = 1 then price end) as yr_1,
             max(case when seqnum = 2 then price end) as yr_2,
             max(case when seqnum = 3 then price end) as yr_3
      from (select p.*,
                   row_number() over (partition by id order by date) as seqnum
            from price_tbl p
           ) p
      group by id;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-12-14
        • 2020-08-16
        • 2021-06-22
        • 1970-01-01
        • 1970-01-01
        • 2015-05-21
        • 2012-05-09
        相关资源
        最近更新 更多