2015-02-17 32 views
0

這會有點複雜。讓我從我的表開始。通過加入多個表來獲取信息

clients [src = 0] 
--------- 
clientID  code   company 
---------  -------  --------- 
1    ABC   ABC Corp 
2    DEF   DEF Corp 


carriers [src = 1] 
--------- 
clientID  code  company 
---------  ------- ------- 
1    ABC   ABC Inc. 
2    JHI   JHI Inc. 


link 
-------- 
contactID  uID  src 
---------  ----- ---- 
1     1  0 
1     1  1 
1     2  0 

contact info 
-------------- 
contactID  fname  lname 
---------  -------  -------- 
1    John  Smith 
2    Quincy  Jones 

所以,我試圖在鏈接表上搜索說「ABC」。鏈接表需要基本上連接到運營商或客戶端表,具體取決於link.src列。它應該找到兩個匹配,一個在客戶端,另一個在運營商,但由於都解決contactID(鏈接表)1,我應該查詢聯繫信息表,並返回

找到1記錄: John Smith

我希望這是有道理的。任何幫助是極大的讚賞!

+0

如果找到的兩個匹配不解析爲相同的'contactID',那麼期望的輸出是什麼?如果只有一場比賽被發現會怎麼樣? – 2015-02-17 22:03:38

+0

在鏈接tbl中,它們都包含1 – Damien 2015-02-17 22:04:49

+0

如果有'contactID = 1',而另一個匹配具有'contactID = 2',或者這種情況不被認爲是可能的,該怎麼辦? – 2015-02-17 22:10:23

回答

2

下面是使用left join一種方法:

select co.* 
from link l left join 
    clients cl 
    on l.src = 0 and l.uid = cl.code left join 
    carriers ca 
    on l.src = 1 and l.uid = ca.code left join 
    contacts co 
    on l.contactid = co.contactid 
where 'ABC' in (co.code, cl.code) 
+0

不會是...... – Damien 2015-02-18 00:33:10

+0

客戶端c ON l.src = 0 AND l.uID = cl.clientID? – Damien 2015-02-18 00:33:49

+0

@Damien。 。 。謝謝。這似乎是正確的列名稱。 – 2015-02-18 17:12:22

0

這是另一種方法。首先,你UNIONClientsCarriers表,並添加一個新的列ContactType區分一個。使用0代替Clients1代替Carriers,與src相同。然後您執行LEFT JOIN以獲得所需的結果。

;WITH Clients(ClientID, Code, Company) AS(
    SELECT 1, 'ABC', 'ABC Corp' UNION ALL 
    SELECT 2, 'DEF', 'DEF Corp' 
) 
,Carriers(ClientID, Code, Company) AS(
    SELECT 1, 'ABC', 'ABC Inc.' UNION ALL 
    SELECT 2, 'JHI', 'JHI Inc.' 
) 
,Link(ContactId, UID, Src) AS(
    SELECT 1, 1, 0 UNION ALL 
    SELECT 1, 1, 1 UNION ALL 
    SELECT 1, 2, 0 
) 
,ContactInfo(ContactID, FName, LName) AS(
    SELECT 1, 'John', 'Smith' UNION ALL 
    SELECT 2, 'Quincy', 'Jones' 
) 
-- START 
,Contact(ContactID, ContactType, Code, Company) AS(
    SELECT 
     ClientID, 0, Code, Company 
    FROM Clients 
    UNION ALL 
    SELECT 
     ClientID, 1, Code, Company 
    FROM Carriers 
) 
SELECT DISTINCT 
    ci.FName, 
    ci.LName 
FROM Link l 
LEFT JOIN Contact c 
    ON c.ContactID = l.UID 
    AND c.ContactType = l.src 
LEFT JOIN ContactInfo ci 
    ON ci.ContactID = c.ContactID 
WHERE 
    c.Code = 'ABC' 
0

從造型pov看這個。你有兩個表中的每一個都有相同類型的數據,實體公司。他們唯一的區別是他們的角色或與貴公司的關係。那麼爲什麼不把他們都放在同一個桶裏呢?

Companies: 
ID code Name 
-- ---- --------- 
1 ABC ABC Corp 
2 DEF DEF Corp 
3 JHI JHI Inc. 

如果某家公司只能是一個客戶端或載體,該指定可以被放置在公司表。由於顯然一家公司可以兼得,所以這個稱號放在一個單獨的表格中。以下顯示,公司1'ABC'既是客戶('L')又是運營商('R'),公司2只是客戶,公司3只是運營商。

CompanyRoles: 
CompanyID Type 
--------- ---- 
     1 'L' 
     1 'R' 
     2 'L' 
     3 'R' 

由於公司可以扮演多個角色,因此不需要保留相同數據的多個副本。如果存在依賴於角色的數據,即在客戶端上維護的數據,但不是運營商維護的數據,反之亦然,那麼子表可以保留這些數據。

至於聯繫人,如果一個公司有一個聯繫人,不管角色如何,聯繫人引用可以被添加到公司的表中。如果聯繫人與角色有關,則將其添加到CompanyRoles表中。

CompanyRoles: 
CompanyID Type ContactID 
--------- ---- --------- 
     1 'L'   1 
     1 'R'   2 
     2 'L'   3 
     3 'R'   4 

想要查看客戶列表嗎?

select c.ID as ClientID, c.Code as ClientCode, c.Name as ClientName, 
     ci.ContactName 
from Companies c 
join CompanyRoles cr 
    on cr.CompanyID = c.ID 
    and cr.Type  = 'L' 
left join Contacts ct -- In case no contact is currently defined 
    on ct.ContactID = cr.ContactID 
join ClientSpecificData csd 
    on csd.ClientID = c.ID; 

想要查看運營商列表?

select c.ID as CarrierID, c.Code as CarrierCode, c.Name as CarrierName, 
     ci.ContactName 
from Companies c 
join CompanyRoles cr 
    on cr.CompanyID = c.ID 
    and cr.Type  = 'R' 
left join Contacts ct -- In case no contact is currently defined 
    on ct.ContactID = cr.ContactID 
join CarrierSpecificData csd 
    on csd.ClientID = c.ID; 

您可以在最後兩個查詢上創建視圖,以便爲僅處理客戶端或僅處理運營商的應用提供單個數據源。視圖上的觸發器可根據需要處理傳入的DML語句,以將數據路由到適當的表。

正如你所看到的,查詢是乾淨和簡單的。數據完整性很簡單,可擴展性不是問題。你還能想要什麼?