Sql Oracle:如何以行的形式查询某些列

Sql Oracle:如何以行的形式查询某些列,sql,oracle,plsql,oracle-xe,Sql,Oracle,Plsql,Oracle Xe,我使用Oracle 11 XE,并具有下表: CREATE TABLE tst (val_a NUMBER, val_b NUMBER, val_c NUMBER, val_sum NUMBER, id NUMBER, dt

我使用Oracle 11 XE,并具有下表:

CREATE TABLE tst
(val_a                          NUMBER,
val_b                          NUMBER,
val_c                          NUMBER,
val_sum                        NUMBER,
id                             NUMBER,
dt                             DATE)
一些样本数据:

INSERT INTO tst 
VALUES(12,15,17,44,1,TO_DATE('2018-03-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'));
INSERT INTO tst 
VALUES(14,16,11,41,1,TO_DATE('2018-03-03 00:00:00', 'YYYY-MM-DD HH24:MI:SS'));
INSERT INTO tst 
VALUES(6,7,8,21,2,TO_DATE('2018-03-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'));
我需要指定两个日期并得到以下结果(
NEW_VAL
SUM
A
B
C
对于
ID=1和DT=2018-03-03
OLD_VAL
ID=1和DT=2018-03-01
)的值:

下面是我实现的查询:

select id, x, new_val, old_val from(

select tst_new.id id0, 1, tst_new.id, 'SUM' x, tst_new.val_sum new_val, tst_old.val_sum old_val from tst tst_new, 
(select * from tst where dt=to_date('01.03.2018', 'dd.mm.yyyy')) tst_old
where tst_new.dt=to_date('03.03.2018', 'dd.mm.yyyy') and tst_new.id = tst_old.id and tst_new.id = 1

UNION ALL

select tst_new.id, 2, null, 'A',  tst_new.val_a, tst_old.val_a from tst tst_new, 
(select * from tst where dt=to_date('01.03.2018', 'dd.mm.yyyy')) tst_old
where tst_new.dt=to_date('03.03.2018', 'dd.mm.yyyy')  and tst_new.id = tst_old.id and tst_new.id = 1

UNION ALL

select tst_new.id, 3, null, 'B', tst_new.val_b, tst_old.val_b from tst tst_new, 
(select * from tst where dt=to_date('01.03.2018', 'dd.mm.yyyy')) tst_old
where tst_new.dt=to_date('03.03.2018', 'dd.mm.yyyy') and tst_new.id = tst_old.id and tst_new.id = 1

UNION ALL

select tst_new.id, 4, null, 'C', tst_new.val_c, tst_old.val_c from tst tst_new, 
(select * from tst where dt=to_date('01.03.2018', 'dd.mm.yyyy')) tst_old
where tst_new.dt=to_date('03.03.2018', 'dd.mm.yyyy') and tst_new.id = tst_old.id and tst_new.id = 1

order by 1, 2
)
它确实提供了所需的结果,但看起来很糟糕。有没有办法让结果更容易

此外,如果没有特定日期的数据,则结果应包含ID、X和空单元格。如果两个日期中的任何一个都没有数据,那么我的查询将不返回任何内容。如果该日期没有值,如何使查询返回空单元格


更新:我已经看到了pivot的示例,但在我的例子中,不仅需要列作为行,还需要查询同一表中不同日期的数据。此外,如果没有特定日期的日期,则不清楚如何获取空单元格。

内部子查询是取消IVOT、外部-向后旋转的结果:

select *
  from (select to_char(dt, 'dd.mm.yyyy') dt, vals, dt_vals from tst
        unpivot (dt_vals for vals in (val_a, val_b, val_c, val_sum)))
 pivot (sum(dt_vals) for dt in ('01.03.2018', '03.03.2018'))
 order by 1

VALS    '01.03.2018' '03.03.2018'
------- ------------ ------------
VAL_A             18           14 
VAL_B             22           16 
VAL_C             25           11 
VAL_SUM           65           41 
接下来,您需要指定如何筛选这些值的规则:

ID=1和DT=2018-03-03的
NEW\u VAL
是值
SUM
A
B
C
OLD\u VAL
是值
ID=1和DT=2018-03-01

我只是将其硬编码为“原样”:


这可能是一个轴心问题。读这个:谢谢。但如何更容易地解决两个不同日期的问题?@S.T.第一步-取消pivot,保留日期,第二步-按分组向后旋转dates@Dmitry请举个小例子好吗?
select *
  from (select to_char(dt, 'dd.mm.yyyy') dt, vals, dt_vals from tst
        unpivot (dt_vals for vals in (val_a, val_b, val_c, val_sum)))
 pivot (sum(dt_vals) for dt in ('01.03.2018', '03.03.2018'))
 order by 1

VALS    '01.03.2018' '03.03.2018'
------- ------------ ------------
VAL_A             18           14 
VAL_B             22           16 
VAL_C             25           11 
VAL_SUM           65           41 
select *
  from (select to_char(dt, 'dd.mm.yyyy') dt, vals, dt_vals from tst
        unpivot (dt_vals for vals in (val_a, val_b, val_c, val_sum))
         where id = 1
         )
 pivot (sum(dt_vals) for dt in ('01.03.2018', '03.03.2018'))
 order by 1

VALS    '01.03.2018' '03.03.2018'
------- ------------ ------------
VAL_A             12           14 
VAL_B             15           16 
VAL_C             17           11 
VAL_SUM           44           41