我有以下表格:
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 )**
有关如何以更有效的方式做到这一点的任何想法?
答案 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 NULL
或NOT 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技术称为排除连接,如果您想了解更多相关信息。所以这个查询的作用是首先找到有错误的行,然后从整个行集中排除它们。