优化IN子查询

时间:2016-02-03 14:22:45

标签: mysql sql join query-optimization 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

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

3 个答案:

答案 0 :(得分:2)

您走在正确的轨道上,但您不需要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表。

答案 1 :(得分:1)

首先,你的加入是错误的!你没有比较两个表上的任何常见列,你应该添加workerGeofences.workerID = w.id这样的地方:

wxBitmap bitmap(my_wxImage_instance);
wxMemoryDC memdc;
memdc.SelectObject(b);
memdc.SetBackground(*wxGREEN_BRUSH);
memdc.Clear();    //fills the entire bitmap with green colour
memdc.SelectObject(wxNullBitmap);
my_wxImage_instance = wxBitmap(bitmap);    //optionally

第二,你没有从第二张表中选择任何东西,所以加入是unessesary,在你的IN语句中,你没有比较正确的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 

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

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 

答案 2 :(得分:1)

使用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