通过连接多个表来获取信息
grabbing information by joining multiple tables
这会有点复杂。让我从我的 table 开始。
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
所以,我正在尝试在 link table 上搜索 "ABC"。 link table 基本上需要根据 link.src 列加入运营商或客户 table。它应该找到两个匹配项,一个在客户中,一个在运营商中,但由于两者都解析为 1 的 contactID (links table),我应该查询联系信息 table和 return
找到 1 条记录:
约翰·史密斯
我希望这是有道理的。非常感谢任何帮助!
这是一种使用 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)
这是另一种方法。首先,您 UNION
Clients
和 Carriers
表并添加一个新列 ContactType
以区分它们。 Clients
使用0
,Carriers
使用1
,与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'
从建模视角看这个。您有两个 table,每个都具有相同类型的数据,即实体 company。他们之间的唯一区别是他们的角色或与贵公司的关系。那为什么不把它们都放在同一个桶里呢?
Companies:
ID code Name
-- ---- ---------
1 ABC ABC Corp
2 DEF DEF Corp
3 JHI JHI Inc.
如果特定公司只能是客户或承运人,则该指定可以放在 Companies table 中。由于显然一家公司可以同时兼具两者,因此该名称进入单独的 table。下图显示公司1'ABC'既是客户('L')又是承运人('R'),公司2只是客户,公司3只是承运人
CompanyRoles:
CompanyID Type
--------- ----
1 'L'
1 'R'
2 'L'
3 'R'
没有必要因为一个公司可以扮演多个角色而保留相同数据的多个副本。如果有依赖于角色的数据,即在客户端维护但不为运营商维护的数据,反之亦然,则 subtables 可以保留该数据。
至于联系人,如果一家公司只有一个联系人,无论职位如何,联系人参考可以添加到 Companies table。如果联系人依赖于角色,则会将其添加到 CompanyRoles table.
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 语句,以将数据路由到适当的 tables。
如您所见,查询简洁明了。数据完整性很容易,可扩展性不是问题。您还想要什么?
这会有点复杂。让我从我的 table 开始。
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
所以,我正在尝试在 link table 上搜索 "ABC"。 link table 基本上需要根据 link.src 列加入运营商或客户 table。它应该找到两个匹配项,一个在客户中,一个在运营商中,但由于两者都解析为 1 的 contactID (links table),我应该查询联系信息 table和 return
找到 1 条记录: 约翰·史密斯
我希望这是有道理的。非常感谢任何帮助!
这是一种使用 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)
这是另一种方法。首先,您 UNION
Clients
和 Carriers
表并添加一个新列 ContactType
以区分它们。 Clients
使用0
,Carriers
使用1
,与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'
从建模视角看这个。您有两个 table,每个都具有相同类型的数据,即实体 company。他们之间的唯一区别是他们的角色或与贵公司的关系。那为什么不把它们都放在同一个桶里呢?
Companies:
ID code Name
-- ---- ---------
1 ABC ABC Corp
2 DEF DEF Corp
3 JHI JHI Inc.
如果特定公司只能是客户或承运人,则该指定可以放在 Companies table 中。由于显然一家公司可以同时兼具两者,因此该名称进入单独的 table。下图显示公司1'ABC'既是客户('L')又是承运人('R'),公司2只是客户,公司3只是承运人
CompanyRoles:
CompanyID Type
--------- ----
1 'L'
1 'R'
2 'L'
3 'R'
没有必要因为一个公司可以扮演多个角色而保留相同数据的多个副本。如果有依赖于角色的数据,即在客户端维护但不为运营商维护的数据,反之亦然,则 subtables 可以保留该数据。
至于联系人,如果一家公司只有一个联系人,无论职位如何,联系人参考可以添加到 Companies table。如果联系人依赖于角色,则会将其添加到 CompanyRoles table.
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 语句,以将数据路由到适当的 tables。
如您所见,查询简洁明了。数据完整性很容易,可扩展性不是问题。您还想要什么?