我有一个visits
表,其中有三列userid
,url
,date
每天用户访问多个页面,我们会在visits
表中为每次访问存储一个条目。
现在我想要一个用户(url
)今天访问但不是昨天访问的userid
列表。
这是我正在尝试的当前查询。
SELECT clickid
FROM visits
WHERE userid='221001'
AND date = '2015-08-20'
AND clickid NOT IN (SELECT clickid FROM visits WHERE userid='221001' AND date = '2015-08-19')
但是这个查询需要花费太多时间。我们的表在内部查询中可能有最多0.2M行
如何让它变得简单快捷?
答案 0 :(得分:0)
来自the answer:
在大多数情况下,JOIN
比子查询更快,并且子查询的速度非常快。
在JOIN
中,RDBMS可以创建一个更适合您的查询的执行计划,并且可以预测应该加载哪些数据进行处理并节省时间,这与子查询不同,它将运行所有查询和加载所有数据以进行处理。
子查询的好处在于它们比JOIN更具可读性:这就是为什么大多数新SQL用户更喜欢它们的原因;这是简单的方法;但是在性能方面,JOIN
在大多数情况下都更好,即使它们也不难阅读。
所以,请尝试这个并告诉我们结果:
select clickid
from visits v1
left join visits v2 on v1.clickid = v2.clickid and v2.date = '2015-08-19'
where v1.userid= '221001'
and v1.date = '2015-08-20'
and v2.clickid is null
或使用NOT EXISTS
:
SELECT v1.clickid
FROM visits v1
WHERE v1.userid='221001'
AND v1.date = '2015-08-20'
AND NOT EXISTS (SELECT NULL FROM visits v2 WHERE v2.userid=v1.userid AND v2.date = '2015-08-19')
PS:如果比较的列(userid
)不可为空,LEFT JOIN
在MySQL上表现最佳。如果列可以为空(值可以为NULL
),则NOT EXISTS
的效果会更好。