我有一个人表,另一个联系人类型(电子邮件、电话等)和一个连接表来保存联系人。
我想构建一个查询来获取一条记录中每个人的电子邮件、电话、邮政信箱,
所以我将有 4 列结果集 UserName、Tel、Email、PO
当我使用 SQL Server 2000 时,XML 不是一个选项。
任何帮助使其工作的帮助将不胜感激。
我有一个人表,另一个联系人类型(电子邮件、电话等)和一个连接表来保存联系人。
我想构建一个查询来获取一条记录中每个人的电子邮件、电话、邮政信箱,
所以我将有 4 列结果集 UserName、Tel、Email、PO
当我使用 SQL Server 2000 时,XML 不是一个选项。
任何帮助使其工作的帮助将不胜感激。
您未能提供有关列的任何有用详细信息,因此我不得不猜测,但我认为您正在寻找类似的东西。
WITH Persons(PersonId, UserName) AS
(
SELECT 1, 'Bob' UNION ALL
SELECT 2, 'Bill'
), ContactTypes(ContactTypeId, Name) AS
(
SELECT 1, 'Tel' UNION ALL
SELECT 2, 'Email' UNION ALL
SELECT 3, 'PO'
),PersonContacts(PersonId, ContactTypeId, Value) As
(
SELECT 1,1,CAST('(01223) 123456' AS VARCHAR(50)) UNION ALL
SELECT 1,2,CAST('bob@example.com' AS VARCHAR(50)) UNION ALL
SELECT 1,3,CAST('1 Acacia Avenue' AS VARCHAR(50)) UNION ALL
SELECT 2,1,CAST('(01223) 654321' AS VARCHAR(50)) UNION ALL
SELECT 2,2,CAST('bill@example.com' AS VARCHAR(50))
)
/*The above Common Table Expressions are just for demo purposes and so you
can see the assumptions. They will not work on SQL Server 2000. You just need
the below.*/
SELECT P.UserName,
/*I've just used the Ids rather than bothering to join on ContactTypes*/
MAX(CASE WHEN C.ContactTypeId = 1 then C.Value END) Tel,
MAX(CASE WHEN C.ContactTypeId = 2 then C.Value END) Email,
MAX(CASE WHEN C.ContactTypeId = 3 then C.Value END) PO
FROM Persons P
LEFT JOIN PersonContacts C ON C.PersonId = P.PersonId
GROUP BY P.PersonId,P.UserName
退货
UserName Tel Email PO
-------- ------------------- ------------------- ------------------
Bob (01223) 123456 bob@example.com 1 Acacia Avenue
Bill (01223) 654321 bill@example.com NULL
我想你想要这个:
SELECT p.username, email.value as email, tel.value as tel, po.value as po
FROM persons p
LEFT JOIN contacts as email ON contacts.person_id = person.id
LEFT JOIN contacts as tel ON contacts.person_id = person.id
LEFT JOIN contacts as po ON contacts.person_id = person.id
WHERE email.type = 'email'
AND tel.type = 'tel'
AND po.type = 'po'
所以你基本上加入了联系人表 3 次,因为联系人表包含 3 种不同形式的联系人。这是一种多态方法,它不能很好地映射到 SQL
此查询的结果应类似于:
username | email | tel | po
John | john@john.com | 012364342 | 1234AA
Sarah | sarah@sarah.com | NULL | NULL
我认为马丁的解决方案也可以,但我对 CASE-WHEN-THEN-END 不太满意
我们必须对您的架构进行猜测,因为您没有在问题的初始版本中向我们提供关键信息:
SELECT P.UserName, T.Tel, E.Email, O.PO
FROM Persons AS P
LEFT JOIN (SELECT J.UserName, C.ContactInfo AS Tel
FROM Contacts AS C
JOIN Junction AS J ON C.ContactId = J.ContactID
WHERE C.ContactType = 'Tel') AS T
ON P.UserName = T.UserName
LEFT JOIN (SELECT J.UserName, C.ContactInfo AS Email
FROM Contacts AS C
JOIN Junction AS J ON C.ContactId = J.ContactID
WHERE C.ContactType = 'Email') AS E
ON P.UserName = E.UserName
LEFT JOIN (SELECT J.UserName, C.ContactInfo AS PO
FROM Contacts AS C
JOIN Junction AS J ON C.ContactId = J.ContactID
WHERE C.ContactType = 'PO') AS O
ON P.UserName = O.UserName
请注意,应该强制执行一些复杂的约束以使查询正常工作。第一个是给定的人有零个或一个电子邮件地址,零个或一个电话号码,以及零个或一个 PO(这是邮局地址吗?)。如果某人拥有多个这些条目中的任何一个,您根本不会告诉我们什么可能是合适的输出。并且约束执行起来很复杂,因为最简单的版本需要对用户名和联系人类型的组合进行唯一约束,但是这些列不会一起存储在任何单个表中。