根据另一列值的值选择列

时间:2016-06-15 08:29:02

标签: sql oracle oracle11g

我在Oracle数据库中有以下表格:

ID    COLUMN_NAME    FIELD1    FIELD2    FIELD3
-------------------------------------------------
1     FIELD1         red       blue      yellow
2     FIELD3         black     purple    green
3     FIELD2         grey      brown     white

我想根据COLUMN_NAME的值返回其中一个FIELD列的值。

期望的结果:

ID    COLUMN_NAME    FIELD_VALUE
---------------------------------
1     FIELD1         red
2     FIELD3         greeen
3     FIELD2         brown

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

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

SELECT ID, COLUMN_NAME, VALUE_OF_COLUMN(COLUMN_NAME) AS FIELD_VALUE FROM MYTABLE

在没有的Oracle SQL 中使用临时表,没有重构表结构,没有使用脚本如PL / SQL ?

谢谢!

3 个答案:

答案 0 :(得分:4)

没有"灵活的"除非您打算使用动态SQL来获取每个值(这可能会严重降低性能)。

您可以使用CASE

CASE column_name
     WHEN 'FIELD1' THEN field1
     WHEN 'FIELD2' THEN field2
     WHEN 'FIELD3' THEN field3
                   ELSE 'default'
     END AS field_value

DECODE

DECODE( column_name, 'FIELD1', field1, 'FIELD2', field2, 'FIELD3', field3, 'default' )
  AS field_value

或通过取消旋转表格。但是,如果更改列数,则所有这些解决方案都需要更新。

另一种方法是重构你的表:

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 );

答案 1 :(得分:0)

据我所知,Oracle中没有这样的内置功能。您需要在整个表中循环一次,然后使用dynamc sql获取预期记录。

答案 2 :(得分:0)

我有类似的需求,我使用了 oracle 的 INSTR 函数

例如:INSTR(COLUMN1,COLUMN2) > 0 它返回 column2 值在 column1 中的位置。我们可以在 WHERE 子句中使用这个条件,因此它返回所有值。