Sql 将所有列转换为行
我的问题是:Sql 将所有列转换为行,sql,oracle,Sql,Oracle,我的问题是: select * from some_table where id = 4045432 返回包含60多列的单行。我不应该依赖列名(因为列名经常更改,我必须“按原样”获取所有数据,而不必每次更新sql查询) 我想要的是将所有列更改为行,如: COLUMN|VALUE ============= C1|V1 C2|V2 我怎样才能做到这一点 提前谢谢你 您可能需要使用一些动态SQL来实现您的目标 您可以使用Oracle的UNPIVOT关键字将包含许多列的短胖表转换为包含列/值对
select * from some_table where id = 4045432
返回包含60多列的单行。我不应该依赖列名(因为列名经常更改,我必须“按原样”获取所有数据,而不必每次更新sql查询)
我想要的是将所有列更改为行,如:
COLUMN|VALUE
=============
C1|V1
C2|V2
我怎样才能做到这一点
提前谢谢你 您可能需要使用一些动态SQL来实现您的目标 您可以使用Oracle的
UNPIVOT
关键字将包含许多列的短胖表转换为包含列
/值
对的高瘦结果集
以下是一个基于古老的EMP
表的示例:
select empno, col, val from
(
-- This query needs to convert all columns to a common datatype
select empno, ename, job, to_char(sal) sal, to_char(comm) comm, to_char(hiredate, 'YYYY-MM-DD') hiredate, to_char(deptno) deptno
from emp
)
unpivot
(
val for col
in(
ename,
job,
sal,
comm,
hiredate,
deptno
)
)
这就产生了你想要的东西:
EMPNO COL VAL
----- -------- ----------
7839 ENAME KING
7839 JOB PRESIDENT
7839 SAL 5000
7839 HIREDATE 1981-11-17
7839 DEPTNO 10
...
为了使数据有意义,您可能需要将表的主键包含为一列(如EMPNO
)
请注意,必须转换数据类型。如果您试图同时取消日期、数字和文本,则UNPIVOT
机制将不起作用。
因此,您的PL/SQL可能需要在查询DBA\u TAB\u COLS
或USER\u TAB\u COLS
并通过适当的转换建立查询时做一些工作
对于60多个列来说,这可能会很乏味,但对于其他宽表来说,这将是一次性的工作。最简单的方法是使用动态sql,而不用在select语句中编写所有列名。 对基础查询(Tablename/Filter)的任何更改都不需要在select语句中添加相关的列名,因为这将由动态sql负责 创建表:
create table match_results (
match_date date,
location varchar2(20),
home_team_name varchar2(20),
away_team_name varchar2(20),
home_team_points integer,
away_team_points integer
);
插入一行:
insert into match_results values ( date'2018-01-01', 'Snowley', 'Underrated United', 'Terrible Town', 2, 0 );
用于将行转换为列的Pl/sql块:
declare
plsql_block VARCHAR2(500);
lv_col_value VARCHAR2(500);
begin
dbms_output.put_line('ColumnName|Value');
for v1 in (select column_name
from user_tab_columns where table_name ='MATCH_RESULTS'
order by column_id)
loop
--Add filter as desired but restrict result set to one row
plsql_block := 'select ' || v1.column_name || ' from MATCH_RESULTS Where LOCATION = ''Snowley'' and rownum < 2';
execute immediate plsql_block into lv_col_value;
dbms_output.put_line(v1.column_name||'| '||lv_col_value);
end loop;
end;
/
参考DBfiddle演示@
1 rows affected
dbms_output:
ColumnName|Value
MATCH_DATE| 01-JAN-18
LOCATION| Snowley
HOME_TEAM_NAME| Underrated United
AWAY_TEAM_NAME| Terrible Town
HOME_TEAM_POINTS| 2
AWAY_TEAM_POINTS| 0