Как мне сжать этот SQL нескольких вложенных элементов в нечто более вменяемое? - PullRequest
0 голосов
/ 17 февраля 2009

Следующий запрос возвращает одну строку по желанию. Таблица «контракты» имеет 6 полей, каждое из которых содержит свое имя пользователя, для которого я хочу получить имена / фамилии из отдельной таблицы «пользователи». Это отлично работает, но есть что-то более краткое? Я думаю, что решение должно быть чем-то, использующим GROUP BY contract.id, чтобы держать его в одном ряду, но я не могу найти ничего лучше, чем этот набор суб-выбора.

Помощь!

SELECT contracts.field1, contracts.field2, 
(SELECT first_name FROM users WHERE username = service_provider_1),
(SELECT last_name FROM users WHERE username = service_provider_1),
(SELECT first_name FROM users WHERE username = service_provider_2),
(SELECT last_name FROM users WHERE username = service_provider_2),
(SELECT first_name FROM users WHERE username = service_org_business_contact),
(SELECT last_name FROM users WHERE username = service_org_business_contact),
(SELECT first_name FROM users WHERE username = client_service_contact_1),
(SELECT last_name FROM users WHERE username = client_service_contact_1),
(SELECT first_name FROM users WHERE username = client_service_contact_2),
(SELECT last_name FROM users WHERE username = client_service_contact_2),
(SELECT first_name FROM users WHERE username = client_business_contact),
(SELECT last_name FROM users WHERE username = client_business_contact)
FROM contracts
WHERE id = ?

Не было бы так плохо, если бы я мог получить оба имя / фамилию из одного под-выбора ... так что даже с грубым решением о под-выборе у меня вдвое больше деталей думаю, мне нужно ...

РЕДАКТИРОВАТЬ: я понимаю сейчас. Ответом на возможность присоединиться к одной и той же таблице несколько раз является использование псевдонима для таблицы. Спасибо, ребята! Новый код:

SELECT contracts.field1, contracts.field2, 
sp1.first_name, sp1.last_name, 
sp2.first_name, sp2.last_name, 
sobc.first_name, sobc.last_name, 
csc1.first_name, csc1.last_name, 
csc2.first_name, csc2.last_name, 
cbc.first_name, cbc.last_name
FROM contracts
JOIN users AS sp1 ON service_provider_1 = sp1.username
JOIN users AS sp2 ON service_provider_2 = sp2.username
JOIN users AS sobc ON service_org_business_contact = sobc.username
JOIN users AS csc1 ON client_service_contact_1 = csc1.username
JOIN users AS csc2 ON client_service_contact_2 = csc2.username
JOIN users AS cbc ON client_business_contact = cbc.username
WHERE contracts.id = ?

К сожалению, использование объединений почти столь же многословно, как и использование подвыборов, но я предполагаю, что это может быть быстрее?

Ответы [ 4 ]

7 голосов
/ 17 февраля 2009

Почему бы не присоединиться к таблице пользователей 6 раз?

6 голосов
/ 17 февраля 2009
SELECT contracts.field1, contracts.field2, 
sp1.first_name,
sp1.last_name 
sp2.first_name,
sp2.last_name,
/* etc, etc */
FROM
contracts
INNER JOIN
users sp1
ON
contracts.id = sp1.id
AND sp1.username = service_provider_1
INNER JOIN 
users sp2
ON contracts.id = sp2.id
AND sp2.username = service_provider_2
INNER JOIN 
users sobc
ON contracts.id = sobc.id
AND sobc.username = service_org_business_contact
INNER JOIN
/* etc, etc */
WHERE contracts.id = @myid

Вы также хотите объединить first_name и last_name для каждого имени пользователя? Вы можете сделать это как

RTRIM(sp1.first_name) + ' ' + RTRIM(sp1.last_name) as sp1_name

в вашем предложении SELECT. RTRIM необходимы, если тип данных (N) CHAR, необязательно, если тип (N) VARCHAR

РЕДАКТИРОВАТЬ: Как указано в комментариях к этот ответ , присоединение к идентификатору, вероятно, не требуется, и в этом случае оно становится

SELECT 
contracts.field1, 
contracts.field2, 
sp1.first_name,
sp1.last_name 
sp2.first_name,
sp2.last_name,
/* etc, etc */
FROM
contracts
INNER JOIN
users sp1
ON
sp1.username = service_provider_1
INNER JOIN 
users sp2
ON
sp2.username = service_provider_2
INNER JOIN 
users sobc
ON 
sobc.username = service_org_business_contact
INNER JOIN
/* etc, etc */
WHERE contracts.id = @myid

Мой макет, вероятно, делает его длиннее! Возможно, вам придется использовать LEFT OUTER JOINS, если возможно иметь контрактную запись, которая не имеет first_name и last_name для одного из ее полей в таблице пользователей.

5 голосов
/ 17 февраля 2009
select 
 c.field1,c.field2
,SP1.first_name ,SP1.last_name
,SP2.first_name ,SP2.last_name
,SOBC.first_name,SOBC.last_name
,CSC1.first_name,CSC1.last_name
,CSC2.first_name,CSC2.last_name
,CBC.first_name ,CBC.last_name
from contracts C
left join users as SP1  on SP1.Username  = C.service_provider_1 
left join users as SP2  on SP2.Username  = C.service_provider_2 
left join users as SOBC on SOBC.Username = C.service_org_business_contact 
left join users as CSC1 on SP1.Username  = C.client_service_contact_1 
left join users as CSC2 on SP1.Username  = C.client_service_contact_2 
left join users as CBC  on CBC.Username  = C.client_business_contact 

where c.ID = ?
2 голосов
/ 17 февраля 2009

Не могу помочь, но думаю, что выкладывание имен в отдельную таблицу вместе со столбцом для типа имени может быть хорошей идеей.

Редактировать: или иметь другую таблицу соединений, расположенную между контрактами и пользователями, для правильного соединения многих со многими.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...