2016-09-09 10 views
-1

を最適化し、私は、以下のSQLクエリを最適化しようとしていたが、私は、SELECT句内のサブクエリで立ち往生しています。は、以下のSQLクエリ

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句でどのようにサブクラスを選択しているかは誰でも説明できますか?私は、外部クエリのすべての反復でサブクエリが実行されていると思います。そうですか?それを最適化することはできますか?もしそうなら、私を道に導くことができますか?同じテーブルには、選択サブクエリ内で使用して同じテーブルに一致している理由を

EDIT

tb_RemFindingはすでに左に使用されている場合感謝が参加します。どんな助けでも大歓迎です。クエリは他の開発者によって書かれており、私はそれを書き直そうとしています。あなたのサブクエリが実際に、再び実行されたすべての反復で

+1

TOPですが、ORDER BYはありません。どうして?サブクエリをスキップし、代わりに左の結合を実行します。 – jarlh

+0

実行計画が飢えています! –

+0

@ jarlh古いコードだったので、注文なしで何をしたのか分からなかった。私はクエリが実際に何をしているのか混乱していました。テーブルはすでに左結合で結合されているので、左結合を行うにはどうすればいいですか? – user3205479

答えて

1

gidその外側のクエリで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)

はその後、次の2つのインデックスをしたいです。

私もTOPORDER BY句の欠如に注意してください。それは通常、問題を示しています。しかし、場合によっては、のいずれかがの任意の値であることが必要なので、クエリの意図によって異なります。

+0

左結合を削除すると、エイリアスRFは無意味になります。 – user3205479

+0

同じ結果が得られますか? OPのクエリでは、countカラムを持つ 't_Finding x t_RemFinding'行を受け取ります。これは 't_Finding'行を生成します。 –

+0

@PawełDyl。 。 。それがまさにポイントです。私はOPがそれらの重複した行をすべて望んでいるとは思わない。 –

1

指定や順序の指定されていない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超えるt_RemFinding上の複数のインデックスとのより良い、それを最適化することができますが、私はあなたが望んでいないと仮定し

+0

ありがとうございますが、サブクエリを完全に排除して結合だけを使用することは可能ですか?クエリを書き直すことはできますか? – user3205479

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 
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' 
0

あなたはOUTERが同様に適用され使用することができますし、全体のクエリからのみ有効にしたい場合は、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' 
0

テーブルのサンプルデータと出力がどのように表示されているのか、この質問には答えにくいです。クエリを見ると、クエリは "gid" IDを返そうとしますが、まだ有効なレコードはRF1.Active = 1であるように見えます。これが正しければ、単純なケースステートメントでその作業を行うべきです。

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' 
関連する問題