SQL查询 - 与连接相反?

时间:2011-07-13 17:17:16

标签: sql optimization

我有以下表格:

Table ROWS ( **RowId**, Title)

Table CELLS ( **CellId**, RowId, Title) 

Table ERRORS ( **ErrorId**, CellId, Title )

因此行可以包含单元格,单元格可能有错误。

如何编写检索单元格没有错误的行的查询?

我知道这样的事情会起作用,但我想知道是否可以以更有效的方式完成:

QUERY1

SELECT ROWS.RowID FROM ROWS 
 JOIN CELLS ON ROWS.RowId = CELLS.RowID 
 JOIN ERRORS ON ERRORS.CellId = CELLS.CellId

QUERY2

SELECT * FROM ROWS 
WHERE ROWS.RowId NOT IN ( QUERY1 )** 

有关如何以更有效的方式做到这一点的任何想法?

5 个答案:

答案 0 :(得分:6)

尝试:
1)

SELECT R.RowID      
FROM ROWS  R LEFT JOIN 
(
    SELECT DISTINCT RowID
      FROM  CELLS  JOIN ERRORS       
              ON ERRORS.CellId = CELLS.CellId 
) C  ON R.RowId = C .RowID
 WHERE C.RowID  IS NULL 

2)或

SELECT ROWS.RowID 
    FROM ROWS   JOIN CELLS 
   ON ROWS.RowId = CELLS.RowID   
WHERE NOT EXISTS
(
    SELECT 1
      FROM   ERRORS 
        WHERE ERRORS.CellId = CELLS.CellId 
)    

答案 1 :(得分:1)

有些人已就此问题进行了研究,请参阅:http://explainextended.com/2009/09/18/not-in-vs-not-exists-vs-left-join-is-null-mysql/

结论是:使用LEFT JOIN / IS NULLNOT IN。不要使用NOT EXISTS;那个慢了。

我想我会计算每行的错误,并对其进行过滤:

select cells.rowid from cells 
left join errors on errors.cellid=cells.cellid 
group by cells.rowid 
having count(errorid)=0;

这可以避免所有子选择。

答案 2 :(得分:0)

您可以使用NOT EXISTS构造在单个查询中执行此操作 - 应该比您拥有的更有效

select rows.rowid from rows where not exists (select 1 from cells join errors on errors.cellid = cells.cellid where cells.rowid = rows.rowid)

答案 3 :(得分:0)

如果LEFT JOIN并选择了找不到合作伙伴的所有行呢?

SELECT ROWS.RowID
  FROM ROWS
  JOIN CELLS USING(RowID)
  LEFT JOIN ERRORS ON USING(CellID)
  WHERE ErrorID IS NULL

答案 4 :(得分:0)

对于sql server:

;WITH RowsWithErrors As 
(
    SELECT Distinct r.RowID
    FROM Rows r
    INNER JOIN Cells c ON c.RowID = r.RowID
    INNER JOIN Errors e on e.CellId = c.CellID
)
SELECT r.*
FROM Rows r
LEFT JOIN RowsWithErrors e ON r.RowID = e.RowID
WHERE e.RowID IS NULL

LEFT JOIN / IS NULL技术称为排除连接,如果您想了解更多相关信息。所以这个查询的作用是首先找到有错误的行,然后从整个行集中排除它们。