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查询都出现错误。好吧,我已尽了最大努力。祝您加快查询速度。