通过连接多个表来获取信息

时间:2015-02-17 21:40:02

标签: sql sql-server sql-server-2008

这有点复杂。让我从表格开始。

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记录: 约翰史密斯

我希望这是有道理的。非常感谢任何帮助!

3 个答案:

答案 0 :(得分: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)

答案 1 :(得分:0)

这是另一种方法。首先,您UNION ClientsCarriers表并添加新列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'

答案 2 :(得分: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语句,以将数据路由到适当的表。

如您所见,查询简洁明了。数据完整性很容易,可扩展性不是问题。你还想要什么?