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 dependent 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.
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.