我有两个表vtiger_crmentity和vtiger_crmentityrel(来自开源项目vtiger)。
vtiger_crmentity
+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| crmid | int(19) | NO | PRI | NULL | |
| smcreatorid | int(19) | NO | MUL | 0 | |
| smownerid | int(19) | NO | MUL | 0 | |
| modifiedby | int(19) | NO | MUL | 0 | |
| setype | varchar(30) | NO | | NULL | |
| description | text | YES | | NULL | |
| createdtime | datetime | NO | | NULL | |
| modifiedtime | datetime | NO | | NULL | |
| viewedtime | datetime | YES | | NULL | |
| status | varchar(50) | YES | | NULL | |
| version | int(19) | NO | | 0 | |
| presence | int(1) | YES | | 1 | |
| deleted | int(1) | NO | MUL | 0 | |
| label | varchar(255) | YES | MUL | NULL | |
+--------------+--------------+------+-----+---------+-------+
vtiger_crmentityrel
+-----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| crmid | int(11) | NO | | NULL | |
| module | varchar(100) | NO | | NULL | |
| relcrmid | int(11) | NO | | NULL | |
| relmodule | varchar(100) | NO | | NULL | |
+-----------+--------------+------+-----+---------+-------+
我正在尝试获取crmentityrel表中不存在的联系人列表(在relcrmid列中是特定的)。我可以通过子查询执行此操作,但是大约需要2分钟才能完成(每个表中大约有2万条记录)。
我试图将查询转换为连接,但我肯定做错了,因为我一直得到错误的值(与我知道的子查询相比)。
非常感谢任何帮助。如果您需要我方提供任何详细信息,请告诉我
编辑 - 我的工作查询(带子查询)是 -
SELECT crmid, label from vtiger_crmentity
WHERE deleted = 0 and setype="Contacts"
and crmid not in (select relcrmid from vtiger_crmentityrel
where relmodule="Contacts")
答案 0 :(得分:3)
要将not in
转换为join
,我们的想法是使用left join
和where
:
SELECT c.crmid, c.label
FROM vtiger_crmentity c left join
vtiger_crmentityrel cr
on c.crmid = cr.relcrmid and relmodule = 'Contacts'
WHERE c.deleted = 0 and c.setype = 'Contacts' and cr.relcrmid is null;
我应该指出,上述内容并非完全等同于。如果子查询返回单个NOT IN
值,则NULL
不返回任何行。上述行为更为直观。
由于NOT IN
具有NULL
值的行为,NOT EXISTS
是更好的选择。此外,它通常也有更好的表现:
SELECT crmid, label
FROM vtiger_crmentity c
WHERE deleted = 0 and setype = 'Contacts' AND
NOT EXISTS (SELECT relcrmid
FROM vtiger_crmentityrel cr
WHERE cr.relmodule = 'Contacts' and cr.relcrmid = c.crmid
);