Вложенный оператор SQL - PullRequest
       8

Вложенный оператор SQL

1 голос
/ 24 апреля 2011

У меня есть таблица для персон, другой для типов контактов (электронная почта, тел и т. Д.) и распределительная таблица для сохранения личных контактов.

Я хотел бы создать запрос, чтобы получить электронную почту, тел, ро для каждого человека в одной записи,

, поэтому у меня будет набор результатов из 4 столбцов UserName, Tel, Email, PO

Поскольку я использую SQL Server 2000, XML не вариант.

Буду признателен за любую помощь, чтобы заставить это работать.

Ответы [ 3 ]

1 голос
/ 24 апреля 2011

Вы не смогли предоставить какие-либо полезные сведения о столбцах, поэтому я должен был догадаться, но я думаю, что вы ищете что-то вроде.

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
0 голосов
/ 24 апреля 2011

Мы должны догадаться о вашей схеме, потому что вы не дали нам важную информацию в первоначальной версии вопроса:

Предполагаемая схема

  • Таблица: Персоны -Имя пользователя (PK), ...
  • Таблица: Контакты - ContactType ('Tel', 'Email', 'PO'), ContactInfo, ContactID (PK), ...
  • Таблица: Junction - UserName, 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

Обратите внимание, что существуют некоторые сложные ограничения, которые необходимо применить для созданиязапрос работает вменяемым.Основным является то, что для данного лица существует либо ноль, либо один адрес электронной почты, а также ноль или один номер телефона, а также ноль или один почтовый ящик (это адрес почтового отделения?).Вы просто не говорите нам, что может быть подходящим выходом, если у кого-то есть более одной из этих записей.И ограничения сложны в применении, потому что для самой простой версии требуется уникальное ограничение на комбинацию имени пользователя и типа контакта, но эти столбцы не хранятся вместе ни в одной отдельной таблице.

0 голосов
/ 24 апреля 2011

Я думаю, что вы хотите это:

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

Я думаю, что решение Мартина будет работать, но яя не слишком доволен делом, когда-то-концом

...