此查询显示正确的结果,但在执行EXPLAIN时,它会将其列为“Dependent SubQuery”,我认为这很糟糕?
SELECT Competition.CompetitionID, Competition.CompetitionName, Competition.CompetitionStartDate
FROM Competition
WHERE CompetitionID NOT
IN (
SELECT CompetitionID
FROM PicksPoints
WHERE UserID =1
)
我尝试将查询更改为:
SELECT Competition.CompetitionID, Competition.CompetitionName, Competition.CompetitionStartDate
FROM Competition
LEFT JOIN PicksPoints ON Competition.CompetitionID = PicksPoints.CompetitionID
WHERE UserID =1
and PicksPoints.PicksPointsID is null
但它显示0行。与实际工作的第一个查询相比,上面有什么问题?
答案 0 :(得分:1)
秒查询无法生成行:它声称:
WHERE UserID =1
and PicksPoints.PicksPointsID is null
但为了澄清,我改写如下:
WHERE PicksPoints.UserID =1
and PicksPoints.PicksPointsID is null
因此,一方面,您要求PicksPoints
UserId = 1
处的行,但是您再次希望该行不存在于第一位。你能看到失败吗?
外部联接非常棘手!通常使用“外部”表中的列进行过滤,例如Competition
。但你不希望这样做;你希望过滤左边连接的表。尝试并重写如下:
SELECT Competition.CompetitionID, Competition.CompetitionName, Competition.CompetitionStartDate
FROM Competition
LEFT JOIN PicksPoints ON (Competition.CompetitionID = PicksPoints.CompetitionID AND UserID = 1)
WHERE
PicksPoints.PicksPointsID is null
有关详情,请阅读此nice post。
但是,作为一个额外的注释,在性能方面,使用子查询或左连接会遇到一些麻烦。
使用子查询会遇到麻烦,因为 5.6 (已完成一些好的工作),MySQL在优化内部查询方面非常糟糕,并且您的子查询预计会执行多次。
使用LEFT JOIN
您遇到麻烦,因为LEFT JOIN
指示从左到右的加入顺序。然而,您的过滤位于正确的表中,这意味着您将无法使用索引来过滤USerID = 1
条件(或者您将失去连接的索引)。
答案 1 :(得分:0)
这是两个不同的查询。第一个查询查找与用户ID 1相关的竞争(通过PicksPoints
表),第二个查询与 与用户ID 1相关联的那些行加入,另外还有一个null { {1}}。
第二个查询是空的,因为您要加入一个名为PicksPointsID
的表,并且您正在查找连接结果中PicksPoints
为空的行。只有在
PicksPointsID
和一个竞争ID,与第一个表格中的竞争ID相匹配,或者由于PickPointsID
真的听起来像一个主键,所以它出现了案例2。因此PicksPointsID
中的所有列都为null,您的where子句(PickPointsID
)将始终为false,结果将为空。
普通的左连接应该适合你
UserID=1 and PicksPoints.PicksPointsID is null
用select c.CompetitionID, c.CompetitionName, c.CompetitionStartDate
from Competition c
left join PicksPoints p
on (c.CompetitionID = p.CompetitionID)
where p.UserID <> 1
替换最终where
(制作复杂的连接子句)也可能有效。我将留给您分析每个查询的计划。 :)
我个人并不认为需要进行and
测试。由Shlomi Noach链接的文章非常好,您可以在那里找到一些技巧来帮助您。