嵌套 SQL 语句

发布于 2024-11-03 06:42:33 字数 203 浏览 5 评论 0原文

我有一个人员表,还有一个联系人类型表(电子邮件、电话等) 和一个用于保存人员联系人的联结表。

我想构建一个查询来获取一条记录中每个人的电子邮件、电话、邮政地址,

因此我将有 4 列结果集用户名、电话、电子邮件、邮政地址

当我使用 SQL Server 2000 时,XML 不是一个选项。

任何帮助使其发挥作用的帮助将不胜感激。

I have a table for persons, anothor for types of contacts(email, tel, etc.)
and a junction table to save person contacts.

I'w like to construct a query to get email, tel, po for each person in one record,

so I will have 4 columns result set UserName, Tel, Email, PO

As I use SQL Server 2000, XML is not an option.

Any help to get this to work will be appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

烛影斜 2024-11-10 06:42:33

您未能提供有关列的任何有用的详细信息,因此我不得不猜测,但我认为您正在寻找类似的内容。

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('[email protected]' 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('[email protected]' 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      [email protected]     1 Acacia Avenue
Bill     (01223) 654321      [email protected]    NULL

You have failed to provide any useful details about columns so I had to guess but I think you are looking for something like.

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('[email protected]' 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('[email protected]' 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

Returns

UserName Tel                 Email               PO
-------- ------------------- ------------------- ------------------
Bob      (01223) 123456      [email protected]     1 Acacia Avenue
Bill     (01223) 654321      [email protected]    NULL
邮友 2024-11-10 06:42:33

我认为你想要这样:

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     | [email protected]   | 012364342 | 1234AA
Sarah    | [email protected] | NULL      | NULL

我认为马丁的解决方案也可以工作,但我对 CASE-WHEN-THEN-END 不太满意

I think you want this:

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'

So you basically join on the contacts table 3 times because the contacts table contains 3 different forms of contacts. This is a polymorphic approach and it doesn't map well to SQL

The result of this query should be something like:

username | email           | tel       | po
John     | [email protected]   | 012364342 | 1234AA
Sarah    | [email protected] | NULL      | NULL

I think martin's solution will work as well but I'm not too happy with the CASE-WHEN-THEN-END

呆橘 2024-11-10 06:42:33

我们必须猜测您的架构,因为您没有在问题的初始版本中向我们提供关键信息:

假设的架构

  • 表:人员 - 用户名 (PK),...
  • 表:联系人 - ContactType ('Tel', 'Email', 'PO'), ContactInfo, ContactID (PK), ...
  • 表:连接点 - 用户名,ContactID - 组合上的 PK,每列上的 FK

可能的查询

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(这是邮局地址吗?)。如果某人拥有多个这些条目,您根本不会告诉我们什么可能是合适的输出。而且约束执行起来很复杂,因为最简单的版本需要对用户名和联系人类型的组合进行唯一约束,但这些列不会一起存储在任何单个表中。

We have to make guesses about your schema because you didn't give us the crucial information in the initial version of the question:

Assumed schema

  • Table: Persons - UserName (PK), ...
  • Table: Contacts - ContactType ('Tel', 'Email', 'PO'), ContactInfo, ContactID (PK), ...
  • Table: Junction - UserName, ContactID - PK on the combo, FK on each column

Possible query

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

Note that there are some complex constraints that should be enforced to make the query work sanely. The primary one is that there is either zero or one email address for a given person, and zero or one telephone number, and zero or one PO (is that a Post Office address?). You simply don't tell us what might be appropriate output if someone has more than one of any of these entries. And the constraints are complex to enforce because the simplest version would require a unique constraint on the combination of user name and contact type, but those columns are not stored together in any single table.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文