#sql #oracle11g
#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, я не знаком с методами, которые вы используете (операторы case, условная агрегация и поворот). Это нельзя сделать с помощью JOIN и SELECT? Пожалуйста, извините мое невежество в этом вопросе. (Дело не в том, что меня не интересуют превосходные методы, но я не хочу двигаться слишком быстро слишком рано.)
Комментарии:
1. Я некоторое время возился с этим, и единственной другой вещью, которая могла бы работать для этого, было бы несколько объединений, и это может даже не подходить для этого сценария. Ваш самый простой вариант — использовать CASE , который является просто циклом IF для SQL.
Ответ №1:
Один из способов приблизиться к этому — условная агрегация:
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:
Кажется, сводный (oracle.com ) здесь было бы легко работать.
SELECT ID, SIN, PHONE, EMAIL
FROM PEOPLE
PIVOT (
MAX(CONTACT)
FOR TYPE IN ('EMAIL', 'PHONE')
)
Ответ №3:
Я понимаю, что это менее элегантно, чем все опубликованные решения, но здесь это так или иначе, решение, использующее только 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.