是否可以使用EXISTS而不是DISTINCT的IN子句来优化查询

时间:2018-11-01 12:34:48

标签: mysql sql distinct exists

我有有效的查询。

select contract_no AS c_no, cm_mac AS c_mc, MIN(tstamp) as time2, sum(1) as aps
from devices where 
contract_no in 
(select distinct(contract_no) from devices where 
tstamp >= '2018-10-28 06:59:59' AND tstamp <= '2018-10-29 07:00:00')
group by contract_no, cm_mac;

我意识到查询速度很慢,所以我想知道是否仍然可以优化此查询? 我当时在想也许要用EXISTS代替IN,但是那样的话我就不能以EXISTS (SELECT 1 from .... where contract_no= contract_no )开头,因为我需要这个DISTINCT子句。

我当然需要返回相同的结果。 是否可以通过某种方式优化此查询?

UPDATE:

我检查了反馈,您说得对。如果执行这两个查询,我将得到相同的结果。 但是关键是完整查询更加复杂,如果我没有此子查询,则会得到更多结果。

查询1(返回正确的72行):

    SELECT id, contract_no, customer, address, cm_mac, aps 
    FROM (select * from new_installed_devices where  insert4date >='2018-10-28' 
    AND insert4date <='2018-10-28' AND install_mark<2) as d1 
left join 
( select * from (select contract_no AS c_no, cm_mac AS c_mc, 
MIN(tstamp) as time2, sum(1) as aps from devices_change 
where contract_no in (select distinct(contract_no) from devices_change 
where tstamp >= '2018-10-28 06:59:59' AND tstamp <= '2018-10-29 07:00:00') 
group by contract_no, cm_mac ) as mtmbl 
where mtmbl.time2 >= '2018-10-28 06:59:59' and mtmbl.time2 <= '2018-10-29 
07:00:00' ) as tmp on d1.contract_no=tmp.c_no 
where aps>0 group by contract_no, customer, address, cm_mac;

查询2(返回不正确的75行),此方法可为您推荐(在其中包含两个查询):

SELECT id, contract_no, customer, address, cm_mac, aps  
FROM (select * from new_installed_devices where  insert4date >='2018-10-28' 
AND insert4date <='2018-10-28' AND install_mark<2) as d1 left join 
( select * from (select distinct(contract_no) AS c_no, cm_mac AS c_mc, 
MIN(tstamp) as time2, sum(1) as aps from devices_change 
where  tstamp >= '2018-10-28 06:59:59' AND tstamp <= '2018-10-29 07:00:00'
 group by contract_no, cm_mac ) as mtmbl 
where mtmbl.time2 >= '2018-10-28 06:59:59' and 
mtmbl.time2 <= '2018-10-29 07:00:00' ) as tmp 
on d1.contract_no=tmp.c_no 
where aps>0 group by contract_no, customer, address, cm_mac;

1 个答案:

答案 0 :(得分:1)

尝试此版本:

select contract_no AS c_no, cm_mac AS c_mc, min(tstamp) as time2, count(*) as aps
from devices d
where exists (select 1
              from devices d2
              where d2.contract_no = d.contract_no and
                    tstamp >= '2018-10-28 06:59:59' and
                    tstamp <= '2018-10-29 07:00:00'
              )
group by contract_no, cm_mac;

您要在devices(contract-no, tstamp)上建立索引。