简体   繁体   English

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

[英]Oracle SQL - Convert N rows' column values to N columns in 1 row

The trick with this compared to the other questions (eg "Oracle convert rows to columns") is that my column values are arbitrary strings, rather than something I can use with decode. 与其他问题(例如“ Oracle将行转换为列”)相比,此方法的窍门是我的列值是任意字符串,而不是我可用于解码的东西。 Take this query: 进行以下查询:

The description table here maps people's names to descriptions, but each person can have multiple descriptions eg "wears a hat" or "is tall". 这里的描述表将人们的名字映射到描述,但是每个人可以有多个描述,例如“戴帽子”或“高”。

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;

I would want an output like this: 我想要这样的输出:

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

In the case of less than 3 descriptions, I want nulls there. 在少于3个描述的情况下,我希望在那里为null。 In the case of more than 3 descriptions, I want to just leave them out. 对于3个以上的描述,我只想省略掉。

I am using Oracle 11.1. 我正在使用Oracle 11.1。 Can this be done efficiently? 可以有效地做到这一点吗?

Assuming that you don't care what order the descriptions are returned in (ie Jeremy Smith could just as correctly have a Description1 or "Confused" and a Description2 of "Tall"), you just need to pivot on the row number. 假设您不在乎描述以什么顺序返回(即Jeremy Smith可以正确地将Description1或“ Confused”和Description2为“ Tall”),则只需要对行号进行旋转即可。 If you care about the order the descriptions are returned in, you can add an ORDER BY clause to the window function in the ROW_NUMBER analytic function 如果您关心返回描述的顺序,则可以在ROW_NUMBER分析函数的window函数中添加ORDER BY子句

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

As an aside, I'm hoping that you're actually storing a birth date and computing the person's age rather than storing the age and assuming that people are updating their age every year. 顺便说一句,我希望您实际上是在存储一个出生日期并计算该人的年龄,而不是存储年龄并假设人们每年都在更新自己的年龄。

I have tried this option, but it says we should give order by clause inside row analytics function as shown below, 我已经尝试过此选项,但是它说我们应该在行分析功能内给出order by子句,如下所示,

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

It works fine for my scenario when i put order by clause. 当我按order by子句时,它对我的​​情况很好用。

My scenario is user details are in table A, usergroups are in table C, and association between users and usergroups in table B. One user can have multiple usergroups. 我的情况是用户详细信息在表A中,用户组在表C中,并且用户和用户组之间的关联在表B中。一个用户可以有多个用户组。 I need to get results with username with multiple usergroups in a single row 我需要在一行中包含多个用户组的用户名获得结果

** **

Query: 查询:

** **

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;

** **

Query Result 查询结果

** **

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM