【问题标题】:Oracle SQL - Convert N rows' column values to N columns in 1 rowOracle SQL - 将 N 行的列值转换为 1 行中的 N 列
【发布时间】:2012-03-08 08:46:33
【问题描述】:

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

【问题讨论】:

    标签: sql oracle pivot


    【解决方案1】:

    假设您不关心返回描述的顺序(即 Jeremy Smith 可以正确地拥有 Description1 或“Confused”和“Tall”的 Description2),您只需要旋转在行号上。如果你关心描述返回的顺序,你可以在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
    

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

    【讨论】:

    • 我不在乎订购,所以我会尝试。至于你的“旁白”,这个查询是一个简单的捏造,以避免包含我实际查询的许多细节:)
    • 这花了我很长时间才弄清楚如何使用,但是一旦我得到它,它就完美地工作了(我对连接逻辑感到困惑——这对于这种技术来说并不是明确必要的,它是真的就像给每一行一个行号然后使用行号来标识一行一样简单)。谢谢!
    【解决方案2】:

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

    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)
    

    【讨论】:

      猜你喜欢
      • 2017-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多