我的查询似乎需要花费太长时间才能执行。自从我做了很多非常简单的选择/更新和v.simple连接之后,已经有一段时间了(几年),所以我在这里不仅仅是生锈了!
SELECT count(distinct r.TAGCODE)
FROM RAWREADS r
where r.TAGCODE NOT IN (
select distinct r.TAGCODE
from RAWREADS r, checkpoints c, guards g, INCIDENTITEMS i
where r.TAGCODE = c.TAGNO
or r.TAGCODE = g.IDTAG
or r.TAGCODE = i.IDTAG
);
内部选择似乎工作正常,如果缓慢(几秒钟),但只要我添加外部'计数不在'我最终不得不杀死我的数据库连接 - 所以没有好工作到应用程序! ;)
我希望上面的查询清楚我想要实现的目标...获取所有rawread标记,其中该标记与checkpoints / guards / incidentitems中的相应列不匹配。
我正在使用Flamebird数据库服务器(没有选择)和FlameRobin来运行查询,如果这很重要。
在某些时候,我还需要向外部选择添加一个查询,以确保我不选择tagcode为null或“”的任何rawreads。
我已经从out选项中删除了一个“char_length(tagcode)> 0”标准,以期加快速度,但我认为我的问题比这更基本。
答案 0 :(得分:3)
许多数据库(也可能是Firebird)无法轻松优化NOT IN条件。因此,您可能会尝试将其重写为NOT EXTISTS。
另外看一下内部选择,我认为你加入那里的方式是产生太多行。它不是真正的连接,也不是笛卡尔产品。无论如何,我可以想象在那里做UNION也更有效率。
所以试试这个:
SELECT count(distinct r.TAGCODE)
FROM RAWREADS r
where NOT EXISTS (
select 1
from checkpoints c
where c.tagno = r.tagcode
union all
select 1
from guards g
where g.idtag = r.tagcode
union all
select 1
from INCIDENTITEMS i
where i.idtag = r.tagcode);
如果您的checkpoints(tagno)
,guards(idtag)
和incidentitems(idtag)
上的索引应该运行得相当快。
答案 1 :(得分:2)
NOT IN
中的每个行都会调用RAWREADS
内的子查询,因此此查询运行缓慢。如果您作为过程运行,则将子查询结果转储到临时表中,并使用该临时表执行内部联接,并对TAGCODE
执行负面条件
答案 2 :(得分:1)
SELECT count(distinct r.TAGCODE)
FROM RAWREADS r
where NOT EXISTS (
select *
from checkpoints c, guards g, INCIDENTITEMS i
where r.TAGCODE = c.TAGNO
or r.TAGCODE = g.IDTAG
or r.TAGCODE = i.IDTAG
);
如果是sql server
SELECT count(distinct r.TAGCODE)
FROM RAWREADS r
where NOT EXISTS (
select TOp 1 1
from checkpoints c, guards g, INCIDENTITEMS i
where r.TAGCODE = c.TAGNO
or r.TAGCODE = g.IDTAG
or r.TAGCODE = i.IDTAG
);
答案 3 :(得分:0)
下面的代码与Firebird 2.5兼容,而且速度很快。 我现在无法测试,但这是主意。 它使用CTR来简化子查询代码。
with SQ1 as (
select distinct r.TAGCODE as TAGCODE
from RAWREADS r, checkpoints c, guards g, INCIDENTITEMS i
where r.TAGCODE = c.TAGNO
or r.TAGCODE = g.IDTAG
or r.TAGCODE = i.IDTAG
)
SELECT count(distinct r.TAGCODE)
FROM RAWREADS r
left join SQ1 on (r.TAGCODE = SQ1.TAGCODE)
where SQ1.TAGCODE is NULL
答案 4 :(得分:0)
在任何RDBMS中,获取优化的NOT IN子句的最佳方法是在WHERE子句中编写带有失败条件的LEFT OUTER JOIN,如下所示:
SELECT count(distinct r.TAGCODE)
FROM RAWREADS r
left outer join checkpoints c on r.TAGCODE = c.TAGNO
left outer join guards g on r.TAGCODE = g.IDTAG
left outer join INCIDENTITEMS i on r.TAGCODE=i.IDTAG
where
c.TAGNO is null AND
g.IDTAG is null AND
i.IDTAG is null
从一般观点来看,这样的NOT IN子句:
select * from TABLEA
where TABLEA.ID NOT IN (SELECT ID from TABLEB)
可以成功转换成
select TABLEA.*
from TABLEA
left outer join TABLEB ON TABLEA.ID=TABLEB.ID
where TABLEB.ID is null
如果TABLEB在列ID上有索引,那么查询在TABLEA中检索TABLEB中没有对应项的所有记录的确非常快