繁体   English   中英

优化IN子查询

[英]optimise IN subquery

我有一个worker表和一个关联的workerGeofence表。

CREATE TABLE IF NOT EXISTS `workergeofences` (
`ID` int(11) NOT NULL,
  `WorkerID` varchar(20) NOT NULL,
  `GeofenceID` int(11) NOT NULL,
  `isActive` tinyint(4) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=107 DEFAULT CHARSET=latin1;

我只需要返回在workerGeofences表中具有至少一个isActive为1的条目的工人。

我可以通过以下方法获得所需的结果:

    SELECT distinct w.ID, Title, FName, SName, Email, Birthday, Address, Phone, description,
 companyID 
FROM Workers w WHERE companyID = ? 
and w.ID IN (SELECT WorkerID FROM WorkerGeofences WHERE isActive <> 0)
    limit ?,10

但是in子查询是详尽无遗的,因为当我运行解释时,我可以看到它正在扫描整个表。 我该如何解决?

您处在正确的轨道上,但是您不需要select distinct 除非您知道有重复项,否则这会减慢查询速度-这不太可能,因为您正在选择WOrkers.Id

SELECT w.* 
FROM Workers w 
WHERE w.companyID = ? AND
      EXISTS (SELECT 1
              FROM workerGeofences wg
              WHERE w.ID = wg.WorkerID AND wg.isActive <> 0
             )
LIMIT ?, 10;

然后,对于此查询,您需要在Workers(CompanyId, Id)workerGeofences(WorkerId, isActive)上建立索引。

注意:为方便起见,我仅输入select * 我假设所有列都来自Workers表。

首先,您的加入是错误的! 您没有在两个表上比较任何公共列,则应在其中添加workerGeofences.workerID = w.id,如下所示:

SELECT  w.ID, Title, FName, SName, Email, Birthday, Address, Phone,
        description, companyID
    FROM  Workers w
    join  workerGeofences
    WHERE  workerGeofences.workerID = w.ID companyID = ?
      and  w.ID IN (
        SELECT  WorkerID
            FROM  WorkerGeofences s
            WHERE  isActive <> 0
              and  s.workerID = w.id
                   )
    limit  0,10 

其次,您没有从第二个表中选择任何内容,因此联接是不必要的,并且在您的IN语句中,您没有在比较正确的ID,因此您的查询应为:

SELECT  w.ID, Title, FName, SName, Email, Birthday, Address, Phone,
        description, companyID
    FROM  Workers w
    WHERE  companyID = ?
      and  w.ID IN (
        SELECT  WorkerID
            FROM  WorkerGeofences s
            WHERE  isActive <> 0
              and  s.workerID = w.ID
                   )
    limit  0,10 

另外,您可以为此使用EXISTS()。

SELECT  w.ID, Title, FName, SName, Email, Birthday, Address, Phone,
        description, companyID
    FROM  Workers w
    WHERE  companyID = ?
      and  exists 
      ( SELECT  1
            FROM  WorkerGeofences s
            WHERE  isActive = 1
              and  s.workerID = w.ID
      )
    limit  0,10

为了确保使用JOIN的完整性:

SELECT DISTINCT w.ID,
       w.Title, 
       w.FName, 
       w.SName, 
       w.Email, 
       w.Birthday, 
       w.Address, 
       w.Phone, 
       w.description, 
       w.companyID
  FROM Workers w 
  JOIN WorkerGeofences wg
    ON wg.workerID = w.id
   AND wg.isActive = 1
 WHERE w.companyID = ? 
 LIMIT ?,10

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM