如何通过 SQL 获取动态生成的数据透视?

问题描述 投票:0回答:1
输入

这是我已有的桌子。

table

DateState 一起构成复合主键。假设我们有来自所有 50 个州的几个月的每日数据。

我想要什么

像这样的旋转视图,其中Date是主键。

enter image description here

我见过的一些查询片段(下面的示例)似乎对数据透视列(State)的每个值使用硬编码的分组依据,这似乎无法扩展到五十个州。根据问题的不同,当它绝对不可行时,甚至可能有超过 50 个值。

SELECT 
    start_dt, 
    SUM(
      CASE WHEN state = 'NY' THEN sales ELSE 0 END
    ) AS NY, 
    SUM(
      CASE WHEN state = 'CA' THEN sales ELSE 0 END
    ) AS CA, 

  FROM 
    sales_raw
  GROUP BY 
    start_dt; 

那么无需硬编码即可执行此操作的 SQL 方法是什么?

方言

如果相关,我正在使用谷歌大查询。如果假设解决方案中的任何函数在 BQ 中可用,那就最好了。

sql pivot query-optimization
1个回答
0
投票

恐怕如果不硬编码 PIVOT 子句或 Case 表达式,就无法完成此操作(仅在纯 sql 中)。另一方面,可以像这样创建一个动态生成的 sql 命令,可以使您免于硬编码:

WITH      S a m p l e    D a t a :
    tbl (A_DATE, STATE_CODE, SALES) AS
        ( Select To_Date('01.03.2024', 'dd.mm.yyyy'), 'NY', 63 From Dual Union All 
          Select To_Date('02.03.2024', 'dd.mm.yyyy'), 'CA', 57 From Dual Union All
          Select To_Date('01.03.2024', 'dd.mm.yyyy'), 'CA', 39 From Dual Union All
          Select To_Date('02.03.2024', 'dd.mm.yyyy'), 'NY', 21 From Dual 
        ) 
--  Generating dynamic sql command
SELECT      'Select A_DATE, ' || Chr(10) || Chr(9) || Chr(9) || Chr(9) || 
                              LISTAGG(Distinct s.STTMT, ', ' || Chr(10) || Chr(9) || Chr(9) || Chr(9) ) 
                              WITHIN GROUP (Order By t.A_DATE, t.STATE_CODE) Over() || 
            Chr(10) || 'From tbl t Group By t.A_DATE Order By t.A_DATE ' "CMD"
FROM        tbl t
INNER JOIN ( Select  Distinct 
                      '(Select Sum(SALES) "' || STATE_CODE || '" From tbl Where STATE_CODE = ' || '''' || STATE_CODE || '''' || ' And A_DATE = t.A_DATE Group By A_DATE) "' || STATE_CODE || '"' "STTMT"
              From    ( Select      A_DATE, STATE_CODE, Sum(SALES) "SALES" 
                        From        tbl
                        Group By    A_DATE, STATE_CODE
                        Order By    A_DATE, STATE_CODE
                      )
          ) s ON( 1 = 1 )
FETCH FIRST ROW ONLY
/*      R e s u l t :
Select A_DATE, 
      (Select Sum(SALES) "CA" From tbl Where STATE_CODE = 'CA' And A_DATE = t.A_DATE Group By A_DATE) "CA",    
      (Select Sum(SALES) "NY" From tbl Where STATE_CODE = 'NY' And A_DATE = t.A_DATE Group By A_DATE) "NY"   
From tbl t Group By t.A_DATE Order By t.A_DATE                             
*/

如果您针对上面的示例数据运行生成的 SQL ...

/*    F i n a l    R e s u l t :
A_DATE           CA         NY
-------- ---------- ----------
01.03.24         39         63
02.03.24         57         21    */
© www.soinside.com 2019 - 2024. All rights reserved.