I have a database that looks like:
contacts
id | name 1 | bob 2 | jack 3 | jill
contactsGroupLink
cId| gId 1 | 1 2 | 3 2 | 3 2 | 5 3 | 4
So basically,
a contact is linked to a group by an entry in the contactsGroupLink table.
A contact may be in multiple groups, but a contact may only be on a group once.
The query I want to write is
select `name`
from contacts
where contact.id not in (select contactId
from contactsGroupLink
where groupId = 5);
Which works.
It returns bob
and jill
.
however its not very optimized as it has a dep开发者_如何转开发endent sub-query. can anyone help optimize it?
Because both columns are unlikely to be NULL, in MySQL (only) the best option is to use the LEFT JOIN/IS NULL:
SELECT c.name
FROM CONTACTS c
LEFT JOIN CONTACTSGROUPLINK cgl ON cgl.contactid = c.id
AND cgl.groupid = 5
WHERE cgl.contactid IS NULL
If the columns were nullable, NOT EXISTS
is a better choice:
SELECT c.name
FROM CONTACTS c
WHERE NOT EXISTS (SELECT NULL
FROM CONTACTSGROUPLINK cgl
WHERE cgl.contactid = c.id
AND cgl.groupid = 5)
The two columns in the CONTACTSGROUPLINK
table should be the primary key, which will automatically index the columns (as of ~5.0+?). Otherwise, make sure the columns are indexed.
...
where not exists (
select 1 from contactsGroupLink cgl
where cgl.contactid = contact.id and cgl.groupid = 5
)
This should efficiently use the index by contactsGroupLink(contactid, groupid) you already have.
精彩评论