是否可以使用exists而不是带有distinct的in子句来优化查询

vvppvyoh  于 2021-06-18  发布在  Mysql
关注(0)|答案(1)|浏览(447)

我有一个问题。

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开始 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;
1dkrff03

1dkrff031#

尝试此版本:

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) .

相关问题