The following query returns a single row, as desired. The 'contracts' table has 6 fields, each with a different username in it, for which I want to retrieve first/last names from a separate 'users' table. This works fine, but is there something more concise? I'm think the solution must be something using GROUP BY contracts.id to keep it one row, but I can't seem to find anything better than this slew of sub-selects.
Help!
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 = ?
It wouldn't be so bad if I could get both first/last name from a single sub-select... so even with a cruddy sub-select solution I have twice the verbosity I should think I need...
EDIT: I get it now. The answer to being able to join to the same table multiple times is to use an alias for the table. Thank folks! New code is:
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 = ?
Sadly, using joins is almost as verbose as using the subselects, but I assume it might be faster?
为什么不加入6次用户表?
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
did you also want to combine first_name
and last_name
for each username? You can do this like
RTRIM(sp1.first_name) + ' ' + RTRIM(sp1.last_name) as sp1_name
in your SELECT clause. The RTRIM are necessary if the data type is (N)CHAR, not necessary if the type is (N)VARCHAR
EDIT: As stated in the comments on this answer , the JOIN on id is probably not necessary, in which case it becomes
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
My layout probably makes it appear longer! You may need to use LEFT OUTER JOINS if it is possible to have a contract record that doesn't have a first_name
and last_name
for one of it's fields within the users table.
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 = ?
I can't help but think that pushing the names out to a separate table along with a column for the name type might be a good idea here.
Edit: Or have another join table sitting between contracts and users to do a many-to-many join properly.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.