Sql “子查询有多行用于相似比较
我在下面有一张桌子 在下面的查询中,外部查询与子查询在标记列上进行类似的比较Sql “子查询有多行用于相似比较,sql,sql-server,pi-db,Sql,Sql Server,Pi Db,我在下面有一张桌子 在下面的查询中,外部查询与子查询在标记列上进行类似的比较 SELECT top 6 * FROM [piarchive].[picomp2] WHERE tag Like ( Select distinct left(tag,19) + '%' from (SELECT * FROM [piarchive].[picomp2] WHERE tag like '%CPU_Active' and time between '2014/10/02
SELECT top 6 *
FROM [piarchive].[picomp2]
WHERE tag Like
(
Select distinct left(tag,19) + '%'
from (SELECT *
FROM [piarchive].[picomp2]
WHERE tag like '%CPU_Active' and time between '2014/10/02 15:13:08'and'2014/10/02 15:18:37'
and value=-524289 order by time desc) as t1
)
and tag not like '%CPU_Active' and tag not like '%Program%' and time between '2014/10/02
15:13:08'and'2014/10/02 15:18:37' order by time desc
但此子查询返回多行,导致以下错误:
错误:当用作表达式时,子查询最多可以返回一行
将where标记(如…where…是子查询)替换为where exists…,并将like比较带到子查询中
SELECT top 6 *
FROM [piarchive].[picomp2]
WHERE tag Like
(
Select distinct left(tag,19) + '%'
from (SELECT *
FROM [piarchive].[picomp2]
WHERE tag like '%CPU_Active' and time between '2014/10/02 15:13:08'and'2014/10/02 15:18:37'
and value=-524289 order by time desc) as t1
)
and tag not like '%CPU_Active' and tag not like '%Program%' and time between '2014/10/02
15:13:08'and'2014/10/02 15:18:37' order by time desc
我在外部查询中添加了一个表别名,以消除标记列的歧义,但是您可以看到类似的比较被转移到子查询中
SELECT top 6 *
FROM [piarchive].[picomp2]
WHERE tag Like
(
Select distinct left(tag,19) + '%'
from (SELECT *
FROM [piarchive].[picomp2]
WHERE tag like '%CPU_Active' and time between '2014/10/02 15:13:08'and'2014/10/02 15:18:37'
and value=-524289 order by time desc) as t1
)
and tag not like '%CPU_Active' and tag not like '%Program%' and time between '2014/10/02
15:13:08'and'2014/10/02 15:18:37' order by time desc
我不能保证这将在大型数据集上执行,但这是另一个主题。就我个人而言,我会寻找一种方法来完全摆脱子查询,因为它都是查询同一个表
更多关于优化的信息
优化起来并不容易,索引在这里几乎没有用处,原因如下:
连接条件t0.tag(如leftt1.tag,19+“%”)并不简单,查询优化程序可能很难生成比嵌套循环更好的东西,即为外部查询的每一行执行子查询。这可能是您最大的性能杀手。
所有类似的比较都不能使用表索引,因为它们检查的是值的结尾,而不是开始。
您唯一的希望可能是,如果日期范围检查具有高度选择性,则会删除大量记录。由于在外部和内部查询中都会对时间字段执行相同的检查,因此您可以将其选择到临时表中:
select left(tag, 19) as key, *
into #working
from [piarchive].[picomp2]
where [time] between '2014/10/02 15:13:08' and '2014/10/02 15:18:37';
现在工作只有指定时间段内的记录。由于您的示例范围非常窄,只有5 1/2分钟,我敢打赌这可能会删除约99%的记录。时间索引将显著加快速度。完成此操作后,您只处理一小部分数据
然后,可能会看到后面的索引键:
然后按以下步骤完成查询的其余部分:
select a.*
from #working a
where exists
(
select *
from #working b
where a.key = b.key and b.tag like '%cpu_active'
)
and
a.tag not like '%program%'
and
a.tag not like '%cpu_active'
我所做的是根据连接条件(标记的前19个字符)创建一个聚集索引,以优化子查询。您必须对此进行测试,因为如果创建索引的成本超过了收益,则可能不会产生任何影响,甚至会减慢速度。这将取决于您拥有的数据量和其他因素。通过将速度提高约5%,我只获得了最小的收益,尽管我只是针对我收集的几百行测试数据运行此操作。数据越多,它应该越有效。使用DISTINCT并不能保证只返回一行。它只有助于确保返回的每一行都是dist增量。可能有数千个不同的行,所有这些行都不同于其他行。如何执行所有这些查询?是否应该按顺序执行?是的,只是按顺序。我会首先尝试运行两个select语句,而不会混淆索引。如果它们运行得足够快,满足您的要求,则可以停止。如果没有,请添加工作临时表上的索引如图所示,并查看其区别。如果运行2条select语句,则其给出错误:[SQL解析器][第2行]“into”附近出现语法错误。我认为此工作临时表的语法形式不正确。当我同时运行这两个select查询时,两个select查询都出现错误。好吧,我已尽了最大努力。祝您加快查询速度。