2013-03-14 32 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結合嗎?

感謝您的任何幫助。


編輯

我的數據,上表聯繫是這樣的:

ID | AddressID | PhoneID | EmailID 

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

提出的解決方案,除了工作,我得到的每ID 3行。合理?

+0

讓我撥打[bluefeet](http://stackoverflow.com/users/426671/bluefeet)。 – Kermit 2013-03-14 19:35:04

+0

在http://mattgemmell.com/2008/12/08/what-have-you-tried/「我有什麼試過桶」:我已經嘗試過使用PIVOT,CASE,COALESCE的各種版本。我可以發佈他們,雖然沒有工作,我擔心這會讓我的帖子感到困惑。 – 2013-03-14 19:40:19

回答

7

可以逆轉置使用CROSS APPLYVALUES子句,以獲得結果的數據:

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 2013-03-14 19:48:31

+0

真棒,從未使用過Cross應用過。後續問題 - >我是否必須在初始SELECT中列出所有列,或者最初的SELECT是否需要與您在Cross Apply中放置的內容匹配')d(ContactMethod,id,Value1,Value2,Value3)' – 2013-03-14 19:53:11

+0

@RefractedPaladin你不明確的列被放置在'values'子句中,你會希望'select'列表只包含最終結果。以下是所有顯示的示例 - 請參閱此演示 - http://sqlfiddle.com/#!3/cbe50/14 - 但您只想顯示新的未轉義列。合理? :) – Taryn 2013-03-14 19:56:38

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的結帳這個系列: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

如何獲取告訴我聯繫方法的列(即該行來自哪個表?)?謝謝 – 2013-03-14 19:42:31

+0

這將只返回一個包含地址,電子郵件和電話的行。你需要將它們分開嗎? – 2013-03-14 19:47:13

+0

後者查詢缺少一個ON子句。你有沒有想要** CROSS **加入VALUES的東西? – 2013-03-15 06:00:00