根据第三列中的类型代码将列拆分为两列

时间:2014-06-17 18:31:51

标签: sql oracle11g

我的SQL非常生疏。我试图改变这个表格:

+----+-----+--------------+-------+
| ID | SIN |   CONTACT    | TYPE  |
+----+-----+--------------+-------+
|  1 | 737 | b@bacon.com  | email |
|  2 | 760 | 250-555-0100 | phone |
|  3 | 737 | 250-555-0101 | phone |
|  4 | 800 | 250-555-0102 | phone |
|  5 | 850 | l@lemon.com  | email |
+----+-----+--------------+-------+

进入此表:

+----+-----+--------------+-------------+
| ID | SIN |    PHONE     |    EMAIL    |
+----+-----+--------------+-------------+
|  1 | 737 | 250-555-0101 | b@bacon.com |
|  2 | 760 | 250-555-0100 |             |
|  4 | 800 | 250-555-0102 |             |
|  5 | 850 |              | l@lemon.com |
+----+-----+--------------+-------------+

我写了这个查询:

SELECT *
  FROM (SELECT *
          FROM people
         WHERE TYPE = 'phone') phoneNumbers
       FULL JOIN (SELECT *
                    FROM people
                   WHERE TYPE = 'email') emailAddresses
          ON phoneNumbers.SIN = emailAddresses.SIN;

产生:

+----+-----+--------------+-------+------+-------+-------------+--------+
| ID | SIN |   CONTACT    | TYPE  | ID_1 | SIN_1 |  CONTACT_1  | TYPE_1 |
+----+-----+--------------+-------+------+-------+-------------+--------+
|  2 | 760 | 250-555-0100 | phone |      |       |             |        |
|  3 | 737 | 250-555-0101 | phone |    1 |   737 | b@bacon.com | email  |
|  4 | 800 | 250-555-0102 | phone |      |       |             |        |
|    |     |              |       |    5 |   850 | l@lemon.com | email  |
+----+-----+--------------+-------+------+-------+-------------+--------+

我知道我可以选择我想要的列,但SIN列不完整。我似乎记得我应该第三次加入这个表来获得一个完整的SIN列,但我不记得是怎么做的。

如何制作目标表(ID,SIN,PHONE,EMAIL)?

编辑和澄清:我很感激到目前为止我收到的答案,但作为一个SQL新手,我不熟悉你正在使用的技术(案例陈述,条件聚合和转动)。这可以不使用JOIN和SELECT完成吗?请原谅我对这件事的无知。 (并不是说我对优秀的技术不感兴趣,但我不想太快过快。)

3 个答案:

答案 0 :(得分:3)

解决这个问题的一种方法是条件聚合:

select min(ID), SIN, 
       max(case when type = 'phone' then contact end) as phone,
       max(case when type = 'email' then contact end) as email
from people t
group by sin;

答案 1 :(得分:1)

似乎pivot(oracle.com)在这里很容易使用。

SELECT ID, SIN, PHONE, EMAIL
FROM PEOPLE
PIVOT (
    MAX(CONTACT)
    FOR TYPE IN ('EMAIL', 'PHONE')
)

答案 2 :(得分:0)

我意识到这不如发布的所有解决方案都优雅,但无论如何,它只是一个使用JOIN和SELECT的解决方案:

SELECT sins.SIN, phone, email
  FROM ((SELECT SIN email_sin, contact email
           FROM people
          WHERE TYPE = 'email') email
        FULL JOIN (SELECT SIN phone_sin, contact phone
                     FROM people
                    WHERE TYPE = 'phone') phone
           ON email.email_sin = phone.phone_sin)
       RIGHT JOIN (SELECT DISTINCT SIN FROM people) sins
          ON sins.SIN = phone_sin OR sins.SIN = email_sin;

缺少ID列。