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

发布于 2025-01-06 13:34:42 字数 769 浏览 1 评论 0原文

与其他问题(例如“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。这可以有效地完成吗?

The trick with this compared to the other questions (e.g. "Oracle convert rows to columns") is that my column values are arbitrary strings, rather than something I can use with decode. Take this query:

The description table here maps people's names to descriptions, but each person can have multiple descriptions e.g. "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. In the case of more than 3 descriptions, I want to just leave them out.

I am using Oracle 11.1. Can this be done efficiently?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

白衬杉格子梦 2025-01-13 13:34:42

假设您不关心描述返回的顺序(即 Jeremy Smith 可以正确地拥有 Description1 或“Confused”以及 Description2 的“Tall” ),您只需要以行号为中心进行旋转即可。如果您关心返回描述的顺序,您可以向 ROW_NUMBER 分析函数中的窗口函数添加一个 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

顺便说一句,我希望您实际上是在存储出生日期并计算该人的年龄,而不是存储年龄并假设人们每年都会更新自己的年龄。

Assuming that you don't care what order the descriptions are returned in (i.e. 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. 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

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.

甜柠檬 2025-01-13 13:34:42

我已经尝试过这个选项,但它说我们应该在行分析函数内给出 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)

I have tried this option, but it says we should give order by clause inside row analytics function as shown below,

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

It works fine for my scenario when i put order by clause.

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. 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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文