個人用のテーブル、連絡先の種類 (電子メール、電話など) 用の別のテーブル、および個人の連絡先を保存するためのジャンクション テーブルがあります。
1 つのレコードで各人の電子メール、電話、郵便番号を取得するクエリを作成したいと思います。
だから私は4列の結果セットUserName、Tel、Email、POを持っています
私は SQL Server 2000 を使用しているので、XML はオプションではありません。
これを機能させるための助けをいただければ幸いです。
個人用のテーブル、連絡先の種類 (電子メール、電話など) 用の別のテーブル、および個人の連絡先を保存するためのジャンクション テーブルがあります。
1 つのレコードで各人の電子メール、電話、郵便番号を取得するクエリを作成したいと思います。
だから私は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
クエリを適切に機能させるために強制する必要のある複雑な制約がいくつかあることに注意してください。主なものは、特定の人の電子メール アドレスがゼロまたは 1 つ、電話番号がゼロまたは 1 つ、PO (郵便局の住所ですか?) がゼロまたは 1 つであることです。誰かがこれらのエントリのいずれかを複数持っている場合、何が適切な出力であるかを単純に教えてくれません。また、最も単純なバージョンでは、ユーザー名と連絡先の種類の組み合わせに対して一意の制約が必要になるため、制約を適用するのは複雑ですが、これらの列は単一のテーブルにまとめて格納されることはありません。