2013-03-14 2 views
2

Я не уверен, что мой вопрос сформулирован правильно, но здесь.Заполнение данных столбца на основе исходной таблицы в T-SQL

У меня есть таблица, называемая контактами, которая имеет ссылки FK на таблицы Адрес, адрес электронной почты, телефон (у них есть 1 для многих с контактами). Мне нужно создать запрос, который вытащит все данные и будет иметь столбец с именем Contact Method, который показывает, какая из подкатегорий, из которой была строка.

Contact: ID, AddressID, EmailID, PhoneID 
Address: ID, Line1, City, State 
Email : ID, EAddress 
Phone : ID, Number, Extension 

мне нужно результирующая таблица, чтобы выглядеть следующим образом:

ContactMethod | ID | [Value1] | [Value2] | [Value3] 

Address   2  N5980 Onalaska  WI 
Email   8  [email protected] 
Phone   5  555-5555 1234 

В качестве альтернативы он мог бы перечислить все объединенные столбцы в строке, если это проще, я могу работать с этим, а также. т.е.

ContactMethad | ID | Line1 | City | State | ID | EAddress | ID | Number | Extension 

Я смотрел на PIVOT, что в чистом виде, но не похоже, чтобы решить мою проблему сам по себе. Нужно ли комбинировать его с COALESCE?

Спасибо за любую помощь.


EDIT

Мои данные, на столе Контакт будет выглядеть следующим образом:

ID | AddressID | PhoneID | EmailID 

1  3   null  null 
2  null   null  7 
3  null   5  null 
4  4   null  null 
5  null   6   null 

Предлагаемое решение работает за исключением того, что я получаю 3 строк на ID. Имеют смысл?

+0

Позвольте мне позвонить [bluefeet] (http://stackoverflow.com/users/426671/bluefeet). – Kermit

+0

В http://mattgemmell.com/2008/12/08/what-have-you-tried/ «Что я пробовал ведро»: я пробовал различные версии с помощью PIVOT, CASE, COALESCE. Я могу опубликовать их, хотя не работал, и я беспокоился, что это сделает мой пост путаным. –

ответ

7

Вы можете UNPIVOT данные, используя пункт CROSS APPLY и VALUES, чтобы получить результат:

select d.ContactMethod, d.id, d.Value1, d.Value2, d.Value3 
from contacts c 
left join address a 
    on c.addressid = a.id 
left join email e 
    on c.emailid = e.id 
left join phone p 
    on c.phoneid = p.id 
cross apply 
(
    values 
    ('Address', c.addressid, a.Line1, a.City, a.State), 
    ('Email', c.emailid, e.eAddress, '', ''), 
    ('Phone', c.phoneid, p.number, cast(p.extension as varchar(10)), '') 
) d (ContactMethod, id, Value1, Value2, Value3) 

См SQL Fiddle with Demo.

Это дает результат:

| CONTACTMETHOD | ID | VALUE1 | VALUE2 | VALUE3 | 
----------------------------------------------------- 
|  Address | 2 | N5980 | Onalaska |  WI | 
|   Email | 8 | [email protected] |   |  | 
|   Phone | 5 | 555-5555 |  1234 |  | 

Если вы хотите, чтобы ваш второй результат, то вы можете использовать несколько объединений, чтобы получить его:

select cm.ContactMethod, 
    a.id addressid, 
    a.line1, 
    a.city, 
    a.state, 
    e.id emailid, 
    e.eaddress, 
    p.id phoneid, 
    p.number, 
    p.extension 
from contacts c 
cross join 
(
    VALUES ('Address'),('Email'),('Phone') 
) cm (ContactMethod) 
left join address a 
    on c.addressid = a.id 
    and cm.ContactMethod = 'Address' 
left join email e 
    on c.emailid = e.id 
    and cm.ContactMethod = 'Email' 
left join phone p 
    on c.phoneid = p.id 
    and cm.ContactMethod = 'Phone'; 

См SQL Fiddle with Demo. Результат:

| CONTACTMETHOD | ADDRESSID | LINE1 |  CITY | STATE | EMAILID | EADDRESS | PHONEID | NUMBER | EXTENSION | 
---------------------------------------------------------------------------------------------------------------- 
|  Address |   2 | N5980 | Onalaska |  WI | (null) | (null) | (null) | (null) | (null) | 
|   Email | (null) | (null) | (null) | (null) |  8 | [email protected] | (null) | (null) | (null) | 
|   Phone | (null) | (null) | (null) | (null) | (null) | (null) |  5 | 555-5555 |  1234 | 

Редактировать # 1, на основе ваших изменений вы можете изменить запросы к следующему.

Первый один с тремя value столбцов, то вы можете просто добавить предложение WHERE чтобы отфильтровать любые null значения:

select c.ID, ContactMethod, Value1, Value2, Value3 
from contacts c 
left join address a 
    on c.addressid = a.id 
left join email e 
    on c.emailid = e.id 
left join phone p 
    on c.phoneid = p.id 
cross apply 
(
    values 
    ('Address', c.addressid, a.Line1, a.City, a.State), 
    ('Email', c.emailid, e.eAddress, null, null), 
    ('Phone', c.phoneid, p.number, cast(p.extension as varchar(10)), null) 
) d (ContactMethod, id, Value1, Value2, Value3) 
where value1 is not null 
    or value2 is not null 
    or value3 is not null 

См SQL Fiddle with Demo. Результат:

ID | CONTACTMETHOD |   VALUE1 | VALUE2 | VALUE3 | 
--------------------------------------------------------------- 
| 1 |  Address |    N5980 | Onalaska |  WI | 
| 2 |   Email |   [email protected] | (null) | (null) | 
| 3 |   Phone |   555-5555 |  1234 | (null) | 
| 4 |  Address | 1417 Saint Andrew | La Crosse |  WI | 

Если вы хотите, чтобы результаты в одной строке, то вам нужно будет использовать UNPIVOT функцию:

select * 
from 
(
    select id, 
    case col 
     when 'addressid' then 'address' 
     when 'emailid' then 'email' 
     when 'phoneid' then 'phone' end ContactMethod, 
    contact_id 
    from contacts 
    unpivot 
    (
    contact_id 
    for col in (addressid, emailid, phoneid) 
) unpiv 
) c 
left join address a 
    on c.contact_id = a.id 
    and c.ContactMethod = 'Address' 
left join email e 
    on c.contact_id = e.id 
    and c.ContactMethod = 'Email' 
left join phone p 
    on c.contact_id = p.id 
    and c.ContactMethod = 'Phone'; 

См SQL Fiddle with Demo. Результат этого запроса:

| ID | CONTACTMETHOD | CONTACT_ID |    LINE1 |  CITY | STATE | EADDRESS | NUMBER | EXTENSION | 
-------------------------------------------------------------------------------------------------------------- 
| 1 |  address |   2 |    N5980 | Onalaska |  WI | (null) | (null) | (null) | 
| 2 |   email |   8 |   (null) | (null) | (null) | [email protected] | (null) | (null) | 
| 3 |   phone |   5 |   (null) | (null) | (null) | (null) | 555-5555 |  1234 | 
| 4 |  address |   3 | 1417 Saint Andrew | La Crosse |  WI | (null) | (null) | (null) | 
+0

[*** + 1 ***] (http://www.google.com) – Kermit

+0

Awesome, никогда не использовали Cross Apply before. Следующий вопрос -> Нужно ли мне перечислять все мои столбцы в начальном SELECT, или исходный SELECT должен соответствовать тому, что вы положили в Cross Apply, например. ') d (ContactMethod, id, Value1, Value2, Value3)' –

+0

@RefractedPaladin Ваши столбцы, которые вы отключаете, помещаются в предложение 'values', и вы хотите, чтобы список' select' содержал только конечный результат. Ниже приведен пример всего, что показано: см. Эту демонстрацию - http://sqlfiddle.com/#!3/cbe50/14 - но вы хотите отображать только новые столбцы без ссылок. Смысл? :) – Taryn

0

Гораздо легче добраться до второго расположения столбцов. Для этого нужно просто присоединиться:

SELECT * 
FROM dbo.Contact c 
JOIN dbo.Address a 
ON c.AddressID = a.ID 
JOIN dbo. Email e 
ON c. EmailID = e.ID 
JOIN dbo. Phone p 
ON c. PhoneID = p.ID 

Я просто использовал SELECT *, но вы должны будете фактически перечислить все столбцы, как вы не хотите, чтобы все из них. Если у вас нет строки в каждой дочерней таблице, вам нужно использовать LEFT OUTER JOIN вместо JOIN.

Для получения более подробной информации о JOIN и Checkout этой серии: http://sqlity.net/en/1146/a-join-a-day-introduction/


Если вам нужно несколько строк вы можете использовать это:

SELECT * 
FROM dbo.Contact c 
CROSS JOIN (VALUES('Address','Email','Phone'))X(ContactMethod) 
LEFT JOIN dbo.Address a 
ON c.AddressID = a.ID 
AND X.ContactMethod = 'Address' 
LEFT JOIN dbo. Email e 
ON c. EmailID = e.ID 
AND X.ContactMethod = 'Email' 
LEFT JOIN dbo. Phone p 
ON c. PhoneID = p.ID 
AND X.ContactMethod = 'Phone' 

Преимущество происходит с версией «распространяться» является что вам не нужно иметь дело с несовместимостью типов данных.

+0

Как получить столбец, который сообщает мне метод контакта (т. Е. Какая таблица из этой строки?)? Спасибо –

+0

Это вернет только одну строку, содержащую адрес, адрес электронной почты и телефон. Вам нужны они отдельно? –

+0

В последнем запросе отсутствует одно предложение ON. Возможно, вы имели в виду ** CROSS ** ПРИСОЕДИНЯЙТЕСЬ В ЦЕННОСТЯХ? –

Смежные вопросы