2017-10-12 337 views
0

我有两个表。 第一个'table_fields'SQL oracle获取一行中某一列的值

Type Name Label 
ORG  text1 organisation 
ORG  text2 location 
PERS text1 manager 
PERS text2 gender 
PERS text3 age 

第二个“table_data

Type ID  text1 text2  text3 text4 
ORG  Sven HR  Brussels   
PERS Ludo theo male  43 
ORG  Sara MR  Barcelona 

我尝试做的是像有两个额外的列table_Fields一个表,代表我TABLE_DATA的ID和值table_fields中特定名称的特定列。 我的结果应该是这样的:

Type Name Label   ID_table_data VALUE 
ORG  text1 organisation Sven   HR 
ORG  text2 location  Sven   Brussels 
PERS text1 manager   Ludo   theo 
PERS text2 gender   Ludo   male 
PERS text3 age    Ludo   43 
ORG  text1 organisation Sara   MR 
ORG  text2 location  Sara   Barcelona 

我不知道这样的事情是可能的SQL甲骨文

回答

2

UNPIVOT使用:

SQL Fiddle

的Oracle 11g R2架构设置

CREATE TABLE table_fields (Type, Name, Label) AS 
SELECT 'ORG',  'text1', 'organisation' FROM DUAL UNION ALL 
SELECT 'ORG',  'text2', 'location' FROM DUAL UNION ALL 
SELECT 'PERS', 'text1', 'manager' FROM DUAL UNION ALL 
SELECT 'PERS', 'text2', 'gender' FROM DUAL UNION ALL 
SELECT 'PERS', 'text3', 'age' FROM DUAL; 

CREATE TABLE table_data (Type, ID, text1, text2, text3, text4) AS 
SELECT 'ORG', 'Sven', 'HR', 'Brussels', NULL, CAST(NULL AS VARCHAR2(20)) FROM DUAL UNION ALL 
SELECT 'PERS', 'Ludo', 'theo', 'male',  '43', NULL FROM DUAL UNION ALL 
SELECT 'ORG', 'Sara', 'MR', 'Barcelona', NULL, NULL FROM DUAL; 

查询1

SELECT f.*, 
     d.id, 
     d.value 
FROM table_data 
     UNPIVOT (value FOR name IN (
      text1 AS 'text1', 
      text2 AS 'text2', 
      text3 AS 'text3', 
      text4 AS 'text4' 
     )) d 
     INNER JOIN table_fields f 
     ON (f.type = d.type AND f.name = d.name) 

Results

| TYPE | NAME |  LABEL | ID |  VALUE | 
|------|-------|--------------|------|-----------| 
| ORG | text1 | organisation | Sven |  HR | 
| ORG | text2 |  location | Sven | Brussels | 
| PERS | text1 |  manager | Ludo |  theo | 
| PERS | text2 |  gender | Ludo |  male | 
| PERS | text3 |   age | Ludo |  43 | 
| ORG | text1 | organisation | Sara |  MR | 
| ORG | text2 |  location | Sara | Barcelona | 
1

你正在寻找一个INNER JOIN像:

SELECT t2.* 
     ,t2.ID AS ID_table_data 
     ,CASE 
      WHEN t2.NAME = 'text1' 
       THEN d.text1 
      WHEN t2.NAME = 'text2 ' 
       THEN d.text2 
      WHEN t2.NAME = 'text3 ' 
       THEN d.text3 
      END As VALUE 
FROM table_fields t1 INNER JOIN table_data t2 ON t1.Type = t2.Type 

编辑: 根据我在开始时并未意识到的MT0评论,我编辑了添加CASE语句以匹配预期结果

+0

这将不匹配'table_field.name'与适当的'table_data'列并将列转置为行。 – MT0

+0

@MTO为什么我们要在第一名呢? – apomene

+0

如果'type'是'ORG',那么'text1'列代表'organisation',如果'type'是'PERS',那么它就是'manager'。您没有执行此匹配,因此此查询提供的数据无效。实际上,您正在执行'CROSS JOIN',因为所有'table_field.label'值都会加入到所有'textN'列 - 这是错误的。 – MT0

1

如果你不能够使用UNPIVOT,这是由MT0建议,因为版本不兼容(例如,您正在使用Oracle版本低于11g)这可能适用于您:

with table_fields (type, name, label) as 
(
    select 'ORG', 'text1', 'organisation' from dual union all 
    select 'ORG', 'text2', 'location' from dual union all 
    select 'PERS', 'text1', 'manager' from dual union all 
    select 'PERS', 'text2', 'gender' from dual union all 
    select 'PERS', 'text3', 'age' from dual 
), 
table_data (type, id, text1, text2, text3, text4) as 
(
    select 'ORG', 'Sven', 'HR', 'Brussels', null, null from dual union all 
    select 'PERS', 'Ludo', 'theo', 'male', '43', null from dual union all 
    select 'ORG', 'Sara', 'MR', 'Barcelona', null, null from dual 
) 
select tf.type, tf.name, tf.label, td.id id_table_data, 
     case 
     when tf.name = 'text1' then td.text1 
     when tf.name = 'text2' then td.text2 
     when tf.name = 'text3' then td.text3 
     when tf.name = 'text4' then td.text4 
     else null 
     end value 
    from table_fields tf 
inner join table_data td on (td.type = tf.type); 
+0

您可以使用ANSI-92标准的连接语法'FROM table_fields tf(而不是使用传统的逗号连接语法(难以阅读并且无法处理完整的外部连接) INNER JOIN table_data td ON(tf.type = td.type)'。 – MT0

+0

@ MT0我刚刚做到了,尽管我个人不同意我们应该全部切换到SQL-92的普遍共识。在我看来,SQL-89语法更易于阅读;我甚至发现外连接的Oracle语法比SQL-92更容易阅读(除非它明显是完全外连接) - 但这可能更多取决于个人偏好和旧习惯。我同意SQL-92应该通常用于答案,尤其是因为问题通常是由刚开始挑选习惯的新手Oracle开发人员提出的。 –

相关问题