Oracle:转换多行以设置列数

时间:2016-07-18 23:08:25

标签: sql oracle oracle11g

我对SQL世界很新(2天),我基本上有以下三个表(表的内容已更改,但问题仍然相同)

名称表

+----+-----------+
| ID | CHARACTER |
+----+-----------+
| 1  | Bones     |
+----+-----------+
| 2  | Booth     |
+----+-----------+
| 3  | Angela    |
+----+-----------+
| 4  | Hodgins   |
+----+-----------+
| 5  | Sweets    |
+----+-----------+

角色表

+---------+------------+
| ROLE_ID | ROLE       |
+---------+------------+
| A       | Squint     |
+---------+------------+
| B       | Unemployed |
+---------+------------+
| C       | Cop        |
+---------+------------+
| D       | Young      |
+---------+------------+
| E       | Crazy      |
+---------+------------+
| F       | Smart      |
+---------+------------+

NameAndRole表

+--------------+----+---------+
| NAME_ROLE_ID | ID | ROLE_ID |
+--------------+----+---------+
| 1            | 1  | A       |
+--------------+----+---------+
| 2            | 1  | C       |
+--------------+----+---------+
| 3            | 1  | E       |
+--------------+----+---------+
| 4            | 1  | F       |
+--------------+----+---------+
| 5            | 2  | C       |
+--------------+----+---------+
| 6            | 3  | A       |
+--------------+----+---------+
| 7            | 4  | A       |
+--------------+----+---------+
| 8            | 4  | E       |
+--------------+----+---------+

我想要的结果是:

+----+-----------+--------+-------+-------+
| ID | CHARACTER | ROLE1  | ROLE2 | ROLE3 |
+----+-----------+--------+-------+-------+
| 1  | Bones     | Squint | Cop   | Crazy |
+----+-----------+--------+-------+-------+
| 2  | Booth     | Cop    |       |       |
+----+-----------+--------+-------+-------+
| 3  | Angela    | Squint |       |       |
+----+-----------+--------+-------+-------+
| 4  | Hodgins   | Squint | Crazy |       |
+----+-----------+--------+-------+-------+
| 5  | Sweets    |        |       |       |
+----+-----------+--------+-------+-------+

即使一个名称在技术上可以拥有超过3个角色,我只想打印第一个3.基于无数谷歌搜索和Oracle读取,我理解我需要使用LEFT JOIN,嵌套SELECT和一个PIVOT。我有下面的声明,但我知道这是不正确的,因为一个,我需要行中的字符而不是列,这是枢轴子句在这里强有力地做的,并且该语句没有在Oracle中运行,错误:

)ON r. ROLE_ID = NameAndRole. ROLE_ID
               *
Error at line 15
ORA-01748: only simple column names allowed here

代码是:

SELECT n.ID,
n.CHARACTER

FROM Names n

LEFT JOIN NameAndRole nr ON n.ID = nr.ID
LEFT JOIN 
(
    (
    SELECT * 
    FROM Roles r
    )
    PIVOT
    (
        MAX(r.role) FOR NameAndRole.NAME_ROLE_ID IN (‘Bones’,’Booth’,’Angela’)
        WHERE NameAndRole.NAME_ROLE_ID<3

    )
)ON r. ROLE_ID = NameAndRole. ROLE_ID

/*I’m not sure as to how much of this is garbage and what’s even usable at this point...*/

P.S - 这是我关于Stack的第一个问题所以如果我没有遵循一些众所周知的规则,请随时告诉我。

1 个答案:

答案 0 :(得分:0)

即使您可以修复错误,我也不确定您的查询是否有效。我也不是100%确定pivot在这里工作得有多好,因为你想要的列名与值不匹配。

但是,您仍然可以使用条件聚合和row_number分析函数来获得所需的结果。此外,如果您愿意,可以非常简单地添加3个以上的角色。

select n.id,
       n.character,
       max(case when r.rn = 1 then r.role end) as role1,
       max(case when r.rn = 2 then r.role end) as role2,
       max(case when r.rn = 3 then r.role end) as role3
  from names n
  left join (select nr.id,
                    r.role,
                    row_number() over (
                      partition by nr.id
                          order by nr.name_role_id) as rn
               from NameAndRole nr
               join roles r
                 on r.role_id = nr.role_id) r
    on r.id = n.id
 group by n.id, n.character
 order by n.id