这有点复杂。让我从表格开始。
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记录: 约翰史密斯
我希望这是有道理的。非常感谢任何帮助!
答案 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
Clients
和Carriers
表并添加新列ContactType
以区分彼此。对0
使用Clients
,1
使用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语句,以将数据路由到适当的表。
如您所见,查询简洁明了。数据完整性很容易,可扩展性不是问题。你还想要什么?