Oracle SQL - 转换N行'列值为1行中的N列

时间:2012-02-16 22:20:43

标签: sql oracle pivot

与其他问题(例如“Oracle将行转换为列”)相比,这个技巧是我的列值是任意字符串,而不是我可以用于解码的东西。接受这个问题:

这里的描述表将人们的姓名映射到描述,但每个人可以有多个描述,例如: “戴帽子”或“身材高大”。

Select firstName, lastName, 
(Select description from descriptions --This can return any number of rows (0 or more)
 where description.firstName = people.firstName
 and description.lastName = people.lastName
 and rownum <= 3)
from people
where age >= 25;

我想要一个像这样的输出:

FIRSTNAME LASTNAME DESCRIPTION1 DESCRIPTION2 DESCRIPTION3
Jeremy    Smith    Tall         Confused        (null)
Anne      Smith    (Null)       (Null)          (Null)
Mark      Davis    Short        Smart           Strong

在少于3个描述的情况下,我想要空值。在超过3个描述的情况下,我想暂不公开。

我使用的是Oracle 11.1。这可以有效地完成吗?

2 个答案:

答案 0 :(得分:2)

假设您不关心返回描述的顺序(即Jeremy Smith可以正确地拥有Description1或&#34;困惑&#34;以及Description2 &#34; Tall&#34;),你只需要转动行号。如果您关心返回描述的顺序,可以在ORDER BY分析函数

中向窗口函数添加ROW_NUMBER子句
SELECT firstName, 
       lastName,
       MAX( CASE WHEN rn = 1 THEN description ELSE NULL END ) description1,
       MAX( CASE WHEN rn = 2 THEN description ELSE NULL END ) description2,
       MAX( CASE WHEN rn = 3 THEN description ELSE NULL END ) description3
  FROM (SELECT firstName,
               lastName,
               description,
               row_number() over (partition by lastName, firstName) rn
          FROM descriptions
               JOIN people USING (firstName, lastName)
         WHERE age >= 25)
   GROUP BY firstname, lastname

顺便说一句,我希望您实际存储出生日期并计算个人的年龄,而不是存储年龄并假设人们每年都在更新他们的年龄。< / p>

答案 1 :(得分:0)

我尝试过这个选项,但它说我们应该在行分析函数中给出order by子句,如下所示,

row_number() over (partition by lastName, firstName order by lastName, firstName) rn

当我按顺序排序时,它适用于我的场景。

我的方案是用户详细信息在表A中,用户组在表C中,用户和用户组之间的关联在表B中。一个用户可以有多个用户组。我需要在一行中使用带有多个用户组的用户名来获得结果

**

查询:

**

SELECT username,
MAX( CASE WHEN rn = 1 THEN ugroup ELSE NULL END ) usergroup1,
MAX( CASE WHEN rn = 2 THEN ugroup ELSE NULL END ) usergroup2,
MAX( CASE WHEN rn = 3 THEN ugroup ELSE NULL END ) usergroup3, 
MAX( CASE WHEN rn = 4 THEN ugroup ELSE NULL END ) usergroup4,
MAX( CASE WHEN rn = 5 THEN ugroup ELSE NULL END ) usergroup5,
from (
select 
a.user_name username, 
c.name ugroup,
row_number() over (partition by a.user_name order by a.user_name) rn
from users a,
usergroupmembership b,
usergroups c
where a.USER_NAME in ('aegreen',
'esportspau'
)
and a.user_id= b.user_id
and b.group_id=c.group_id
)group by uname;

**

查询结果

**

USERNAME    USERGROUP1  USERGROUP2  USERGROUP3  USERGROUP4  USERGROUP5
aegreen US_GOLF (null)  (null)  (null)  (null)
esportspau  EMEA - FSERVICE USER_ES_ES  EMEA-CR-ONLY    (null)  (null)