【问题标题】:Pivot and order multiple columns in oracle在 oracle 中旋转和排序多个列
【发布时间】:2021-08-11 03:15:15
【问题描述】:

我知道如何在 oracle 中旋转查询,但我需要按列对结果进行排序

这是桌子:

Customer_id   Month   Sales_amt   Bill_amt
1             1       10          10
2             1       20          20
3             1       30          30
1             2       20          20
2             2       20          0
3             2       30          30

如果我做关键句

SELECT * 
  FROM t
 PIVOT (
        SUM(sales_amt) AS sales, SUM(bill_amt) AS bill FOR month IN (1,2)
       );

结果是:

Customer_id   1_sales 1_bill 2_sales 2_bill 
1             10      10     20      20       

但我需要先获取销售列,然后是账单列

Customer_id   1_sales 2_sales 1_bill 2_bill 
1             10      20      10      20       

请问我怎样才能得到这个订单?

编辑:我需要以动态方式执行此操作,因为我将使用它来生成自动报告

【问题讨论】:

    标签: sql oracle pivot


    【解决方案1】:

    简单 - 不要选择 *,按照您需要的顺序选择显式列。

    请注意,如果自动命名的列以数字开头,您将需要在它们周围使用双引号(并且列名的其余部分将全部大写,而不是您如何显示它们)。

    类似这样的:

    select customer_id, "1_SALES", "2_SALES", "1_BILL", "2_BILL" [ ... ]
    from   ...
    ..........
    

    在执行此操作时,您还可以为列指定更多标准名称(因此它们不以数字开头,因此它们不需要用双引号括起来)。

    【讨论】:

    • 这是一种动态的方式吗?我将月份用作 3 年前数据的“YYYYMM”格式的日期。我不想每年手动制作。
    【解决方案2】:

    您可以将当前查询转换为包含条件聚合逻辑的查询,例如

    SELECT customer_id, 
           SUM(CASE WHEN month = 1 THEN sales_amt END) AS "1_SALES",
           SUM(CASE WHEN month = 2 THEN sales_amt END) AS "2_SALES",
           SUM(CASE WHEN month = 1 THEN bill_amt END) AS "1_BILL",
           SUM(CASE WHEN month = 2 THEN bill_amt END) AS "2_BILL"
      FROM t
     GROUP BY customer_id 
    

    为了使这些列排序。

    要使查询动态化,请使用以下创建存储函数的代码

    CREATE OR REPLACE FUNCTION Get_Pivoted_Sales RETURN SYS_REFCURSOR IS
      v_recordset SYS_REFCURSOR;
      v_sql       VARCHAR2(32767);
      v_cols      VARCHAR2(32767);
    BEGIN
      SELECT LISTAGG('SUM(CASE WHEN month='||month||' THEN '||column_name||' END) AS "'||cn||'"',',') 
              WITHIN GROUP ( ORDER BY column_name DESC, month )        
        INTO v_cols
        FROM ( SELECT DISTINCT month,column_name,month||'_'||RTRIM(column_name,'_AMT') AS cn
                 FROM t
                CROSS JOIN ( SELECT column_name
                               FROM user_tab_cols 
                              WHERE table_name = 'T' 
                                AND column_name NOT IN ('CUSTOMER_ID','MONTH') ) ); 
    
      v_sql :='SELECT customer_id,'|| v_cols ||'
                 FROM t
                GROUP BY customer_id';
    
      OPEN v_recordset FOR v_sql;
      RETURN v_recordset;
    END;
    /
    

    假设表的创建位置

    CREATE TABLE t
    (
      customer_id INT,
      month       INT,
      sales_amt   NUMBER,
      bill_amt    NUMBER
    )
    

    然后从SQL Developer的控制台调用函数

    SQL> DECLARE
        res SYS_REFCURSOR;
    BEGIN
       :res := Get_Pivoted_Sales;
    END;
    /
    
    SQL> PRINT res;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-06
      • 2017-06-15
      • 2011-06-14
      • 1970-01-01
      • 1970-01-01
      • 2022-01-07
      • 1970-01-01
      相关资源
      最近更新 更多