ID label value app_id
--- ----- ----- ------
120 A Alpha 1
120 B Beta 1
120 C Class 1
120 D Delta 1
120 C Alpha 2
120 D Beta 2
120 E Class 2
120 F Delta 2
建设性查询是
WITH data( ID, label, value, app_id ) AS
(
SELECT 120, 'A', 'Alpha', 1 FROM dual UNION ALL
SELECT 120, 'B', 'Beta' , 1 FROM dual UNION ALL
SELECT 120, 'C', 'Class', 1 FROM dual UNION ALL
SELECT 120, 'D', 'Delta', 1 FROM dual UNION ALL
SELECT 120, 'C', 'Alpha', 2 FROM dual UNION ALL
SELECT 120, 'D', 'Beta' , 2 FROM dual UNION ALL
SELECT 120, 'E', 'Class', 2 FROM dual UNION ALL
SELECT 120, 'F', 'Delta', 2 FROM dual
)
SELECT *
FROM data
Idlabel
SELECT * FROM data WHERE ID = 120 AND app_id = 1;
app_id A B C D ID
------ ------ ----- ----- ----- -----
1 Alpha Beta Class Delta 120
SELECT * FROM data WHERE ID = 120 AND app_id = 2;
app_id C D E F ID
------ ------ ----- ----- ----- -----
2 Alpha Beta Class Delta 120
你可以做什么
SELECT *
FROM data
PIVOT
(
MAX(value) FOR label IN ('A' AS "A", 'B' AS "B",'C' AS "C",'D' AS "D")
)
WHERE ID = 120 AND app_id = 1
120 | a | ||
---|---|---|---|
120 | B | 贝塔 | |
delta | 1 | ||
120 | c | alpha | 2 |
120 | d | 贝塔 | |
delta | 2 | ||
P | 代码 | ||
1 | 121 | ||
2 | 121 | r | |
delphi | |||
121 | S | sine | |
CREATE OR REPLACE FUNCTION Get_Pivoted_Labels( i_id data.id%type, i_app_id data.app_id%type )
RETURN SYS_REFCURSOR IS
v_recordset SYS_REFCURSOR;
v_sql VARCHAR2(32767);
v_cols VARCHAR2(32767);
BEGIN
SELECT LISTAGG( ''''||label||''' AS "'||label||'"' , ',' )
WITHIN GROUP ( ORDER BY label )
INTO v_cols
FROM ( SELECT DISTINCT label
FROM data
WHERE ID = i_id AND app_id = i_app_id );
v_sql :=
'SELECT *
FROM data
PIVOT
(
MAX(value) FOR label IN ( '|| v_cols ||' )
)
WHERE ID = :id AND app_id = :aid';
OPEN v_recordset FOR v_sql USING i_id, i_app_id;
RETURN v_recordset;
END;
/
在哪个辅助查询中,其中选择了label
v_cols
),以将其连接到主SQL字符串中,以返回类型'A' AS "A", 'B' AS "B",'C' AS "C",'D' AS "D"
的值。
被援引
SYS_REFCURSOR
示例
带有生成的SQL语句
如果选择列表中的列顺序很重要,则使用以下代码来创建函数
VAR rc REFCURSOR
VAR v_id NUMBER
VAR v_app_id NUMBER
EXEC :rc := Get_Pivoted_Labels(:v_id,:v_app_id);
PRINT rc
这是一个非常普遍的问题,出于简单的原因是答案是“否”。使用Oracle数据库,每个选择语句都必须具有固定且已知的“形状”(列的数量,其名称和数据类型)。在最近的版本中,似乎有“多态表函数”似乎打破了此规则,但实际上它们没有:在解析语句时计算出“形状”,因此在执行开始之前将其固定并知道。
您不想要“多态”(在解析时变形),您需要真正的“动态”(根据数据在执行时间更改形状)。甲骨文不这样做。最接近您可以使用一个SQL语句获得的最接近的是,精确输出包含XML或JSON的列。然后,调用数据库的程序将负责将结果转换为行和列。 其他替代方案是执行一个选择以获取列名并生成第二个选择以获取所需的结果。我写了一个功能来帮助这样做:
https://stewashton.wordpress.com/2018/05/30/impreved-pivot-function/我不会证明这些替代方案中的任何一个,因为它们不会直接回答您的问题。没有问您的问题直接答案。