Split column into two columns based on type code in third column

落爺英雄遲暮 提交于 2020-01-14 17:27:52

问题


My SQL is very rusty. I'm trying to transform this table:

+----+-----+--------------+-------+
| 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 |
+----+-----+--------------+-------+

Into this table:

+----+-----+--------------+-------------+
| 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 |
+----+-----+--------------+-------------+

I wrote this query:

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

Which produces:

+----+-----+--------------+-------+------+-------+-------------+--------+
| 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  |
+----+-----+--------------+-------+------+-------+-------------+--------+

I know that I can select the columns I want, but the SIN column is incomplete. I seem to recall that I should join in the table a third time to get a complete SIN column, but I cannot remember how.

How can I produce my target table (ID, SIN, PHONE, EMAIL)?

Edit and clarification: I am grateful for the answers I have received so far, but as a SQL greenhorn I am unfamiliar with the techniques you are using (case statements, conditional aggregation, and pivoting). Can this not be done using JOIN and SELECT? Please excuse my ignorance in this matter. (It's not that I am not interested in superior techniques, but I do not want to move too fast too soon.)


回答1:


One way to approach this is conditional aggregation:

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;



回答2:


Seems a pivot (oracle.com) would work easily here.

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



回答3:


I realize this is less elegant than all the solutions posted, but here it is anyhow, a solution using only JOIN and 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;

This lacks the ID column.



来源:https://stackoverflow.com/questions/24270940/split-column-into-two-columns-based-on-type-code-in-third-column

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!