- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我需要取消透视一个我无法控制列的表,因此我需要动态获取列名称:这就是我所拥有的
CREATE TABLE test
(
PK VARCHAR2(255 CHAR),
COL1 VARCHAR2(255 CHAR),
COL2 VARCHAR2(255 CHAR),
COL3 VARCHAR2(255 CHAR),
COL4 VARCHAR2(255 CHAR),
COL5 VARCHAR2(255 CHAR),
COL6 NUMBER,
)
declare
sql_stmt clob;
pivot_clause clob;
begin
select listagg('''' || column_name || ''' as "' || column_name || '"', ',') within group (order by column_name)
into pivot_clause
FROM USER_TAB_COLUMNS
WHERE table_name = 'test');
sql_stmt := 'SELECT PK,
VarName,
Valuer,
Max(timestamp) over (Partition by PK) as timestamp,
FROM test
UNPIVOT(Valuer FOR VarName IN (' || pivot_clause || '))';
execute immediate sql_stmt;
end;
返回结果:
Fehlerbericht -
ORA-00904: : invalid identifier
ORA-06512: at line 23
00904. 00000 - "%s: invalid identifier"
*Cause:
*Action:
预期输出如下:
PK|VARNAME|Valuer
1 |Col1 | value1
1 |Col2 | value2
1 |Col3 | value3
1 |Col4 | value4
1 |Col5 | value5
1 |Col6 | 12345
2 |Col1 | value1
2 |Col2 | value2
2 |Col3 | value3
2 |Col4 | value4
2 |Col5 | value5
2 |Col6 | 12345
如果我只是将子选择直接扔到 IN() 中,这与我得到的错误相同
谢谢
最佳答案
您可以使用dbms_output.put_line(sql_stmt)
来查看实际生成的动态SQL,在本例中为:
SELECT PK,
VarName,
Valuer,
Max(timestamp) over (Partition by PK) as timestamp,
FROM test
UNPIVOT(Valuer FOR VarName IN ('COL1' as "COL1",'COL2' as "COL2",'COL3' as "COL3",'COL4' as "COL4",'COL5' as "COL5",'COL6' as "COL6",'PK' as "PK",'TIMESTAMP' as "TIMESTAMP"))
这有很多问题。一般来说,对于这类事情,明智的做法是从您知道有效的静态语句开始,然后找出如何使其动态化,但您似乎没有在这里这样做。
由于动态语句中时间戳后面有尾随逗号,此版本出现ORA-00936:缺少表达式
。我想这是修改发布代码时出现的另一个错误。如果没有它,它会得到您问题中的 ORA-00904: : invalididentifier
。您收到的错误的直接原因是括号中的部分,例如:
'COL1' as "COL1"
引用错误;那应该是:
COL1 as 'COL1'
修复此问题后会出现ORA-00904: "PK": invalididentifier
,因为您的列查找并未排除您不想旋转的列,所以您确实想要:
select listagg(column_name || ' as ''' || column_name || '''', ',')
within group (order by column_name)
into pivot_clause
from user_tab_columns
where table_name = 'TEST'
and column_name not in ('PK', 'TIMESTAMP');
您的下一个问题是您要取消透视的列是不同的数据类型,因此您会得到ORA-01790:表达式必须与相应表达式具有相同的数据类型
。这有点棘手 - 本质上你必须使用合适的格式将所有内容转换为字符串,特别是在涉及日期的情况下。您需要在子查询中进行该转换,然后对结果进行逆透视。一个仅显式处理数字列的示例,以与 unpivot 子句相同的方式生成子查询列:
declare
sql_stmt clob;
subquery clob;
pivot_clause clob;
begin
select listagg(column_name || ' as ''' || column_name || '''', ',')
within group (order by column_name),
listagg(
case when data_type = 'NUMBER' then 'to_char(' || column_name || ')'
else column_name
end || ' as ' || column_name, ',')
within group (order by column_name)
into pivot_clause, subquery
from user_tab_columns
where table_name = 'TEST'
and column_name not in ('PK', 'TIMESTAMP');
sql_stmt := 'select pk,
varname,
valuer,
max(timestamp) over (partition by pk) as timestamp
from (select pk, timestamp, ' || subquery || ' from test)
unpivot(valuer for varname in (' || pivot_clause || '))';
dbms_output.put_line(sql_stmt);
execute immediate sql_stmt;
end;
/
您可以始终将第二个 listagg()
中的每一列转换为 varchar2(255)
,但这样您就无法直接控制格式设置,并且依赖于NLS 设置。
当运行上面的 block 时,现在会生成:
select pk,
varname,
valuer,
max(timestamp) over (partition by pk) as timestamp
from (select pk, timestamp, COL1 as COL1,COL2 as COL2,COL3 as COL3,COL4 as COL4,COL5 as COL5,to_char(COL6) as COL6 from test)
unpivot(valuer for varname in (COL1 as 'COL1',COL2 as 'COL2',COL3 as 'COL3',COL4 as 'COL4',COL5 as 'COL5',COL6 as 'COL6'))
当手动运行时,会得到如下输出:
PK VARNAME VALUER TIMESTAMP
1 COL1 value1 11-AUG-17 15.49.42.239283000
1 COL2 value2 11-AUG-17 15.49.42.239283000
1 COL3 value3 11-AUG-17 15.49.42.239283000
1 COL4 value4 11-AUG-17 15.49.42.239283000
1 COL5 value5 11-AUG-17 15.49.42.239283000
1 COL6 12345 11-AUG-17 15.49.42.239283000
2 COL1 value6 11-AUG-17 15.49.42.340387000
2 COL2 value7 11-AUG-17 15.49.42.340387000
2 COL3 value8 11-AUG-17 15.49.42.340387000
2 COL4 value9 11-AUG-17 15.49.42.340387000
2 COL5 value10 11-AUG-17 15.49.42.340387000
2 COL6 23456 11-AUG-17 15.49.42.340387000
(我在未透视列中设置了具有不同值的虚拟数据,并且仅使用 systimestamp 来获取时间戳列值)。
当你动态运行它时,它实际上并没有做任何事情 - 它被解析但没有完全执行,因为你没有立即执行任何东西。
My plan was to use this in a view
您可以让匿名 block 动态生成 View ,作为一次性事件:
sql_stmt := 'create or replace view your_view_name as
select pk,
varname,
valuer,
max(timestamp) over (partition by pk) as timestamp
from (select pk, timestamp, ' || subquery || ' from test)
unpivot(valuer for varname in (' || pivot_clause || '))';
execute immediate sql_stmt;
然后您只需选择from your_view_name
即可。
每当将新列添加到表中时(希望这种情况很少见并且处于更改控制之下 - 但您实际上不需要动态执行此操作),您只需重新运行该 block 即可重新创建 View 。
关于oracle - 如何使用动态列取消透视 Oracle,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45637308/
我正在 csv 上使用 hadoop 来分析一些数据。我使用sql/mysql(不确定)来分析数据,现在陷入了僵局。 我花了好几个小时在谷歌上搜索,却没有找到任何相关的东西。我需要一个查询,在该查询中
我正在为 Bootstrap 网格布局的“简单”任务而苦苦挣扎。我希望在大视口(viewport)上有 4 列,然后在中型设备上有 2 列,最后在较小的设备上只有 1 列。 当我测试我的代码片段时,似
对于这个令人困惑的标题,我深表歉意,我想不出这个问题的正确措辞。相反,我只会给你背景信息和目标: 这是在一个表中,一个人可能有也可能没有多行数据,这些行可能包含相同的 activity_id 值,也可
具有 3 列的数据库表 - A int , B int , C int 我的问题是: 如何使用 Sequelize 结果找到 A > B + C const countTasks = await Ta
我在通过以下功能编写此查询时遇到问题: 首先按第 2 列 DESC 排序,然后从“不同的第 1 列”中选择 只有 Column1 是 DISTINCT 此查询没有帮助,因为它首先从第 1 列中进行选择
使用 Bootstrap 非常有趣和有帮助,目前我在创建以下需求时遇到问题。 “使用 bootstrap 在桌面上有 4 列,在平板电脑上有 2 列,在移动设备上有 1 列”谁能告诉我正确的结构 最佳
我是 R 新手,正在问一个非常基本的问题。当然,我在尝试从所提供的示例中获取指导的同时做了功课here和 here ,但无法在我的案例中实现这个想法,即可能是由于我的问题中的比较维度更大。 我的实
通常我会使用 R 并执行 merge.by,但这个文件似乎太大了,部门中的任何一台计算机都无法处理它! (任何从事遗传学工作的人的附加信息)本质上,插补似乎删除了 snp ID 的 rs 数字,我只剩
我有一个 df , delta1 delta2 0 -1 2 0 -1 0 0 0 我想知道如何分配 delt
您好,我想知道是否可以执行以下操作。显然,我已经尝试在 phpMyAdmin 中运行它,但出现错误。也许还有另一种方式来编写此查询。 SELECT * FROM eat_eat_restaurants
我有 2 个列表(标题和数据值)。我想要将数据值列 1 匹配并替换为头文件列 1,以获得与 dataValue 列 1 和标题值列 2 匹配的值 头文件 TotalLoad,M0001001 Hois
我有两个不同长度的文件,file2 是一个很大的引用文件,我从中提取文件 1 的数据。 我有一行 awk,我通常会对其进行调整以在我的文件中进行查找和替换,但它总是在同一列中进行查找和替换。 所以对于
假设我有两个表,如下所示。 create table contract( c_ID number(1) primary key, c_name varchar2(50) not
我有一个带有 varchar 列的 H2 表,其检查约束定义如下: CONSTRAINT my_constraint CHECK (varchar_field <> '') 以下插入语句失败,但当我删
这是最少量的代码,可以清楚地说明我的问题: One Two Three 前 2 个 div 应该是 2 个左列。第三个应该占据页面的其余部分。最后,我将添加选项来隐藏和
在 Azure 中的 Log Analytics 中,我为 VM Heartbeat 选择一个预定义查询,我在编辑器中运行查询正常,但当我去创建警报时,我不断收到警报“查询未返回 TimeGenera
在 Azure 中的 Log Analytics 中,我为 VM Heartbeat 选择一个预定义查询,我在编辑器中运行查询正常,但当我去创建警报时,我不断收到警报“查询未返回 TimeGenera
今天我开始使用 JexcelApi 并遇到了这个:当您尝试从特定位置获取元素时,不是像您通常期望的那样使用sheet.getCell(row,col),而是使用sheet.getCell(col,ro
我有一个包含 28 列的数据库。第一列是代码,第二列是名称,其余是值。 public void displayData() { con.Open(); MySqlDataAdapter
我很沮丧:每当我缩小这个网页时,一切都变得一团糟。我如何将网页居中,以便我可以缩小并且元素不会被错误定位。 (它应该是 2 列,但所有内容都合并为 1)我试过 但由于某种原因,这不起作用。 www.o
我是一名优秀的程序员,十分优秀!