MySQL不存在或替代

时间:2018-09-06 19:12:30

标签: mysql sql

一个表格示例,数据和查询一起可以在http://sqlfiddle.com/#!9/2e65dd/3

中找到

我有兴趣查找所有没有特定record_type的不同user_id。

在我的实际情况下,该表很大,其中有几百万条记录,并且在user_id列上有一个索引。尽管我计划通过一次将输出限制为1000来分批检索它。

select distinct user_id from 
records o where 
not exists (
    select * 
    from records i 
    where i.user_id=o.user_id and i.record_type=3) 
limit 0, 1000

是否有更好的方法来满足这一需求?

3 个答案:

答案 0 :(得分:1)

我会这样:

SELECT u.user_id
FROM (SELECT DISTINCT user_id FROM records) AS u
LEFT OUTER JOIN records as r
  ON u.user_id = r.user_id AND r.record_type = 3
WHERE r.user_id IS NULL

这可以避免您的NOT EXISTS解决方案中的相关子查询。

或者,您应该有另一个只列出用户的表,因此您不必执行子查询:

SELECT u.user_id
FROM users AS u
LEFT OUTER JOIN records as r
  ON u.user_id = r.user_id AND r.record_type = 3
WHERE r.user_id IS NULL

无论哪种情况,都将有助于优化JOIN,以在该对列上添加复合索引:

ALTER TABLE records ADD KEY (user_id, record_type)

答案 1 :(得分:1)

我也建议加入,但是我的和Bill K会有所不同:

SELECT DISTINCT r.user_id 
FROM records AS r 
LEFT JOIN (SELECT DISTINCT user_id FROM records WHERE record_type = 3) AS rt3users
   ON r.user_id = rt3users.user_id
WHERE rt3users.user_id IS NULL
;

但是,我不希望有一种替代方法,但是值得检查,因为性能会根据数据的大小和内容而有所不同...

SELECT DISTINCT r.user_id 
FROM records AS r 
WHERE r.user_id NOT IN (
   SELECT DISTINCT user_id 
   FROM records 
   WHERE record_type = 3
)
;

请注意,这与您的原始查询更相似,但消除了原始子查询的相关性。

答案 2 :(得分:0)

您可以创建一个记录类型等于3的临时表,例如

Select distinct user_id
into #users
from records
where record_type=3 

然后在此表上创建唯一索引(或主键)。然后,您将查询两个表中的索引。

我不能说您必须在数据上测试性能会更好。