根据另一列值的值选择列

hbi*_*bit 2 sql oracle oracle11g

我在 Oracle 数据库中有下表:

ID COLUMN_NAME FIELD1 FIELD2 FIELD3
-------------------------------------------------
1 FIELD1 红蓝黄
2 FIELD3 黑紫绿
3 FIELD2 灰棕白

我想根据 COLUMN_NAME 的值返回 FIELD 列之一的值。

想要的结果:

ID COLUMN_NAME FIELD_VALUE
---------------------------------
1 FIELD1 红色
2 FIELD3 绿色
3 FIELD2 棕色

是的,我可以用 CASE 或 IF / THEN / ELSE 构造来做到这一点,但实际上我有大约 50 个 FIELD 列,随着时间的推移,这些列往往会变得更多。因此,这将成为一个也必须维护的查询的野兽。

因此,我正在寻找一种灵活的解决方案,例如(伪代码)

SELECT ID, COLUMN_NAME, VALUE_OF_COLUMN(COLUMN_NAME) AS FIELD_VALUE FROM MYTABLE
Run Code Online (Sandbox Code Playgroud)

使用临时表、重构表结构和使用临时表的情况下,Oracle SQL 中是否有类似的东西?使用 PL/SQL 之类的脚本的?

谢谢!

MT0*_*MT0 5

There is no "flexible" solution unless you are going to use dynamic SQL to get each value (and that will probably seriously degrade performance).

You can use CASE:

CASE column_name
     WHEN 'FIELD1' THEN field1
     WHEN 'FIELD2' THEN field2
     WHEN 'FIELD3' THEN field3
                   ELSE 'default'
     END AS field_value
Run Code Online (Sandbox Code Playgroud)

or DECODE:

DECODE( column_name, 'FIELD1', field1, 'FIELD2', field2, 'FIELD3', field3, 'default' )
  AS field_value
Run Code Online (Sandbox Code Playgroud)

or by un-pivoting the table. However all these solution will require updating if you change the number of columns.

The other way of doing it it to refactor your tables:

CREATE TABLE field_values (
  id          INT,
  field_name  VARCHAR2(20),
  field_value VARCHAR2(20),
  CONSTRAINT field_values__id_fn__pk PRIMARY KEY ( id, field_name )
);

CREATE TABLE ids (
  id          INT PRIMARY KEY,
  column_name VARCHAR2(20),
  CONSTRAINT ids__id_cn__fk FOREIGN KEY ( id, column_name )
                            REFERENCES field_names ( id, field_name )
);

INSERT INTO field_names
SELECT 1, 'FIELD1', 'red'    FROM DUAL UNION ALL
SELECT 1, 'FIELD2', 'blue'   FROM DUAL UNION ALL
SELECT 1, 'FIELD3', 'yellow' FROM DUAL UNION ALL
SELECT 2, 'FIELD1', 'black'  FROM DUAL UNION ALL
SELECT 2, 'FIELD2', 'purple' FROM DUAL UNION ALL
SELECT 2, 'FIELD3', 'green'  FROM DUAL UNION ALL
SELECT 3, 'FIELD1', 'grey'   FROM DUAL UNION ALL
SELECT 3, 'FIELD2', 'brown'  FROM DUAL UNION ALL
SELECT 3, 'FIELD3', 'white'  FROM DUAL;

INSERT INTO ids
SELECT 1, 'FIELD1' FROM DUAL UNION ALL
SELECT 2, 'FIELD3' FROM DUAL UNION ALL
SELECT 3, 'FIELD2' FROM DUAL;

SELECT i.id,
       i.column_name,
       f.field_value
FROM   ids i
       INNER JOIN field_values f
       ON ( i.id = f.id AND i.column_name = f.field_name );
Run Code Online (Sandbox Code Playgroud)