2012-05-10 9 views
0

私はSQL 2000を使用しています。複雑な条件セットに基づいて不要な重複をすべて削除できるようになりましたが、クエリには約3.5分かかりました重複を含むデータを取得します。この重複削除クエリを最適化するにはどうすればよいですか?

クラリティの場合: rpt.HostNameフィールドまたはrpt.SystemSerialNumberフィールドのいずれかが異なる場合は、重複するrpt.Nameフィールドを持つことができます。また、いくつかの列にタイムスタンプがないため、4つの異なる列のタイムスタンプに基づいて保持するエントリを決定する必要があります。

ご協力いただきありがとうございます。

SELECT 
rpt.[Name], 
rpt.LastAgentExecution, 
rpt.GroupName, 
rpt.PackageName, 
rpt.PackageVersion, 
rpt.ProcedureName, 
rpt.HostName, 
rpt.SystemSerialNumber, 
rpt.JobCreationTime, 
rpt.JobActivationTime, 
rpt.[Job Completion Time] 
FROM DSM_StandardGroupMembersProcedureActivityViewExt rpt 
WHERE 
(
    (
     rpt.GroupName = 'Adobe Acrobat 7 Deploy' 
    OR rpt.GroupName = 'Adobe Acrobat 8 Deploy' 
) 
    AND 
    (
     (rpt.PackageName = 'Adobe Acrobat 7' AND rpt.PackageVersion = '-1.0') 
    OR (rpt.PackageName = 'Adobe Acrobat 8' AND rpt.PackageVersion = '-3.0') 
) 
) 
AND NOT EXISTS 
(
    SELECT * 
    FROM DSM_StandardGroupMembersProcedureActivityViewExt rpt_dupe 
    WHERE 
    (
    (
    rpt.GroupName = 'Adobe Acrobat 7 Deploy' 
     OR rpt.GroupName = 'Adobe Acrobat 8 Deploy' 
    ) 
    AND 
    (
    (rpt.PackageName = 'Adobe Acrobat 7' AND rpt.PackageVersion = '-1.0') 
     OR (rpt.PackageName = 'Adobe Acrobat 8' AND rpt.PackageVersion = '-3.0') 
    ) 
    AND 
    (
     (rpt_dupe.[Name] = rpt.[Name]) 
     AND 
     (
     (rpt_dupe.SystemSerialNumber = rpt.SystemSerialNumber) 
    OR (rpt_dupe.HostName = rpt.HostName) 
    ) 
     AND 
     (
     (rpt_dupe.LastAgentExecution < rpt.LastAgentExecution) 
    OR (rpt_dupe.JobActivationTime  < rpt.JobActivationTime) 
    OR (rpt_dupe.JobCreationTime  < rpt.JobCreationTime) 
    OR (rpt_dupe.[Job Completion Time] < rpt.[Job Completion Time]) 
    ) 
    ) 
) 
) 
+0

実際の実行計画(好ましくは推定されていないもの)のスクリーンショットを投稿してください。 – usr

+0

愚かなコメントかもしれませんが、NOT EXISTS句を使用する代わりにキーワードDISTINCTを使用して重複を削除しようとしましたか? –

+0

Dan、あなたは、重複の定義がクエリが返すフィールドのセットに正確に基づいていると仮定しています。合理的な前提ですが、これは必ずしも真実ではありません。 –

答えて

0

理由が句を存在されていません。

一つのことを示唆しているが、左アウターとしてこれを書き換えることで参加:

from <big query> left outer join 
     <dups query> 
     on <all the fields that constitute a match> 
where <dups query>.<some field> is null 

はしばしば不十分最適化するには存在していないではないことを、私を見つけました。

もう一つの提案は、より直接的な実装にこのクエリを変更することです:

ある
with t as (
    SELECT rpt.[Name], rpt.LastAgentExecution, rpt.GroupName, rpt.PackageName, 
      rpt.PackageVersion, rpt.ProcedureName, rpt.HostName, rpt.SystemSerialNumber, 
      rpt.JobCreationTime, rpt.JobActivationTime, rpt.[Job Completion Time] 
    FROM DSM_StandardGroupMembersProcedureActivityViewExt rpt 
    WHERE rpt.GroupName in ('Adobe Acrobat 7 Deploy', 'Adobe Acrobat 8 Deploy') AND 
      ((rpt.PackageName = 'Adobe Acrobat 7' AND rpt.PackageVersion = '-1.0') OR 
      (rpt.PackageName = 'Adobe Acrobat 8' AND rpt.PackageVersion = '-3.0') 
     ) 
) 
select t.* 
from t join 
     (select name, ..., max(id) 
     from t 
     group by name, ... 
    ) tsum 
     on t.id = tsum.id 

は、あなたが明確な希望の列でテーブルをまとめます。行の1つを選択します。ここでは、各行を一意に識別する「id」フィールドがあると仮定します。名前や日付などのフィールドの組み合わせを使用する必要があります。 IDなしでは、これはより困難です。より最近のバージョンのSQLサーバーでは、row_number()を使用できます。

0

これらの線に沿って試してみてください。

SELECT t_main.columns 
FROM table as t_main 
LEFT JOIN 
(
SELECT name, MAX(lastAgentExecution)..... FROM table GROUP BY name,serialnumber, hostname 
) 
as t_joinSerial 
ON t_main.name=t_joinSerial.name,lastAgentExecution etc. 
where (t_main.AdobeStuff and t_joinSerial is NULL) 
+0

MAX(lastAgentExecution)が2つの名前を返し、次に優先度順にMAX(JobActivationTime)またはMAX(JobCreationTime)またはMAX(JobCompletionTime )? – user1367200

+0

あなたは特定のレコードを1つは持っていませんが、あなたはそれぞれのレコードの各フィールドの最大値を持っています。 1つのレコードで最高のlastAgentを持ち、別のレコードで最高のjobActivationを持つ場合は、動作しません。それはこのアプローチでは複雑になります。これは頻繁に行う必要があるクエリですか?複数のステップでそれを解決するために、そのテーブルに追加のフィールドを使用することがありますか? BTW。あなたはIDフィールドを持っていますか? – Johanness

関連する問題