优化以下sql查询

时间:2016-09-09 11:24:39

标签: sql sql-server

我试图优化下面的SQL查询,但我在select子句中遇到了子查询。

select  F.id,

  (select top 1 RF1.gid from t_RemFinding RF1 where RF1.id = RF.id and RF1.active = 1) as GI

   from t_Finding F                             
   left join t_RemFinding RF on RF.id = F.id
   where F.Gid = '1001' 

有人可以解释一下select子句中的select子查询是如何工作的。我想,子查询在外部查询的每次迭代中运行。是对的吗?我能优化吗?如果是这样,你能指导我吗?谢谢

修改

如果tb_RemFinding已经在左连接中使用,为什么在select子查询中使用相同的表并匹配相同的表。任何帮助是极大的赞赏。该查询是由其他开发人员编写的,我正在尝试重写它。

6 个答案:

答案 0 :(得分:1)

在每次迭代中,您的子查询都会再次运行。您现在可以做的最好的事情是通过字段id,active

对t_RemFinding进行多重索引

虽然没有指定和顺序的TOP 1没有多大意义(它可以采取任何满足其条件的记录)。

最好应该是这样的:

select  F.id,

  (select top 1 RF1.gid from t_RemFinding RF1 where RF1.id = RF.id and RF1.active = 1 order by RF1.gid desc) as GI

   from t_Finding F                             
   left join t_RemFinding RF on RF.id = F.id
   where F.Gid = '1001' 

现在你可以通过id,active,gid上的t_RemFinding上的多索引来更好地优化它

答案 1 :(得分:1)

我假设你不想在外部查询中使用join

select F.id,
       (select top 1 RF1.gid
        from t_RemFinding RF1
        where RF1.id = F.id and RF1.active = 1
       ) as GI
from t_Finding F                             
where F.Gid = 1001 ;  -- removed the single quotes

假设F.Gid是一个数字,请不要在常量周围使用单引号。

然后,您需要两个索引:t_Finding(Gid, id)t_RemFinding(id, active, gid)

我还注意到ORDER BY条款缺少TOP。这通常表明存在问题。但有时候,您只需要任意任意值,因此它取决于查询的意图。

答案 2 :(得分:0)

使用 PartitionBy

select
    X.id,
    X.gid as GI
from
(
    select  
        F.id,
        RF.gid as GI,
        ROW_NUMBER() OVER(Partition BY RF.id ORDER BY RF.gid) AS PartNo
    from t_Finding F                             
    left join t_RemFinding RF on RF.id = F.id
        AND RF.active = 1
    where F.Gid = '1001' 
)X
where X.PartNo=1

答案 3 :(得分:0)

您可以使用外部应用运算符。

   SELECT  F.id,t.gid
   FROM t_Finding a
    OUTER APPLY (select top 1 b.gid from t_RemFinding b where b.id = a.id and b.active = 1)t
    WHERE F.Gid = '1001' 

答案 4 :(得分:0)

您也可以使用OUTER APPLY,如果只想从整个查询中激活,您可以在where子句中检查活动状态。

SELECT RF.id, GI.gid  
FROM t_Finding RF
OUTER APPLY (SELECT TOP 1 RF1.gid 
             FROM t_RemFinding RF1 
             WHERE RF1.id = RF.id AND RF1.active = 1 
             ORDER BY RF1.id DESC) AS GI
WHERE RF.Gid = '1001' 

答案 5 :(得分:0)

如果没有表的一些示例数据以及输出应该是什么样子,很难回答这个问题。查看查询时,查询似乎会尝试返回“gid”ID,但仅针对仍处于活动状态的记录RF1.Active = 1。如果这是正确的,那么一个简单的case语句应该可以胜任。

SELECT  F.id,
        ( 
            CASE
                WHEN RF.active = 1 THEN RF.gid
                ELSE NULL
             END
        ) AS GI
FROM t_Finding F                             
LEFT JOIN t_RemFinding RF on RF.id = F.id
WHERE F.Gid = '1001'