这是我已有的桌子。
列 Date 和 State 一起构成复合主键。假设我们有来自所有 50 个州的几个月的每日数据。
像这样的旋转视图,其中Date是主键。
我见过的一些查询片段(下面的示例)似乎对数据透视列(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 中可用,那就最好了。
恐怕如果不硬编码 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 */