【问题标题】:Is it possible to optimize query using the EXISTS instead of IN clause with DISTINCT是否可以使用 EXISTS 而不是带有 DISTINCT 的 IN 子句来优化查询
【发布时间】:2019-04-05 16:23:56
【问题描述】:

我有一个有效的查询。

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:

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

QUERY 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;

QUERY 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;

【问题讨论】:

  • 如果你只有where tstamp &gt;= '2018-10-28 06:59:59' AND tstamp &lt;= '2018-10-29 07:00:00') 没有子查询,它不工作吗?
  • 不起作用!!!返回了我不希望在结果中出现的其他重复行
  • DISTINCT 不是列上的函数,它是 SELECT DISTINCT 的一部分,适用于整个选定的行。写select distinct contract_no ...让代码更清晰!
  • 请在此处提供示例数据集:sqlfiddle.com 并分享它,以便更轻松地为您提供帮助。我认为这只是在某处添加“不同”的问题。
  • 为什么子查询需要select distinct?它不会给出任何结果差异。

标签: mysql sql distinct exists


【解决方案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) 上建立索引。

【讨论】:

  • 嗨@Gordon,感谢您的反馈,但我得到的结果比我的原始代码更多。请看一下,我更新了完整查询的外观,也许您可​​以给我一些提示,如果我尝试排除子查询的那一部分,为什么会返回多行。提前谢谢你
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-18
  • 2014-07-07
  • 1970-01-01
  • 2010-11-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多