2016-09-28 2 views
0

スキーマ情報:この句のサブクエリを単一のクエリに統一する方法はありますか?パフォーマンスを向上させるか?

v_ProjectMilestone参照プロジェクトPROJECT_ID経由

マイルストーンは、内蔵または外付けとすることができる(milestone.is_external = 1)

マイルストーンは、私たちが気に3つの日付列(実際、改訂または提案してきました)

これらの日付のそれぞれに値を持つマイルストーンのパーセンテージと、内部および外部のマイルストーンの間で分割されたすべての日付と、各プロジェクトの両方の組み合わせを確認できます。

with AllMilestones as( 
       SELECT 
        (select count(project_id) 
         from v_ProjectMilestone 
         where v_ProjectMilestone.project_id=pp.record_id) AS all_milestones, 
        (select count(project_id) 
         from v_ProjectMilestone 
         where v_ProjectMilestone.project_id=pp.record_id 
         and Actual_date is not null 
         ) AS all_Actual_milestones, 
        (select count(project_id) 
         from v_ProjectMilestone 
         where v_ProjectMilestone.project_id=pp.record_id 
         and Actual_date is null 
         and proposed_date is not null 
         and revised_date is null 
         ) AS all_Proposed_milestones, 
        (select count(project_id) 
         from v_ProjectMilestone 
         where v_ProjectMilestone.project_id=pp.record_id 
         and Actual_date is null 
         and revised_date is not null 
         ) AS all_Revised_milestones, 
        (select count(project_id) 
         from v_ProjectMilestone 
         where v_ProjectMilestone.project_id=pp.record_id 
         and 
         (Actual_date is not null 
         or revised_date is not null 
         or proposed_date is not null) 
         ) AS all_scheduled_milestones,     

        (select count(project_id) 
         from v_ProjectMilestone 
         where v_ProjectMilestone.project_id=pp.record_id 
         and is_external=1) AS External_milestones, 
        (select count(project_id) 
         from v_ProjectMilestone 
         where v_ProjectMilestone.project_id=pp.record_id 
         and Actual_date is not null 
         and is_external=1 
         ) AS External_Actual_milestones, 
        (select count(project_id) 
         from v_ProjectMilestone 
         where v_ProjectMilestone.project_id=pp.record_id 
         and Actual_date is null 
         and proposed_date is not null 
         and revised_date is null 
         and is_external=1 
         ) AS External_Proposed_milestones, 
        (select count(project_id) 
         from v_ProjectMilestone 
         where v_ProjectMilestone.project_id=pp.record_id 
         and Actual_date is null 
         and revised_date is not null 
         and is_external=1 
         ) AS External_Revised_milestones, 
        (select count(project_id) 
         from v_ProjectMilestone 
         where v_ProjectMilestone.project_id=pp.record_id 
         and is_external=1 
         and 
         (Actual_date is not null 
         or revised_date is not null 
         or proposed_date is not null) 
         ) AS External_scheduled_milestones,           

        (select count(project_id) 
         from v_ProjectMilestone 
         where v_ProjectMilestone.project_id=pp.record_id 
         and is_external=0) AS internal_milestones, 
        (select count(project_id) 
         from v_ProjectMilestone 
         where v_ProjectMilestone.project_id=pp.record_id 
         and Actual_date is not null 
         and is_external=0 
         ) AS internal_Actual_milestones, 
        (select count(project_id) 
         from v_ProjectMilestone 
         where v_ProjectMilestone.project_id=pp.record_id 
         and Actual_date is null 
         and proposed_date is not null 
         and revised_date is null 
         and is_external=0 
         ) AS internal_Proposed_milestones, 
        (select count(project_id) 
         from v_ProjectMilestone 
         where v_ProjectMilestone.project_id=pp.record_id 
         and Actual_date is null 
         and revised_date is not null 
         and is_external=0 
         ) AS internal_Revised_milestones, 

        (select count(project_id) 
         from v_ProjectMilestone 
         where v_ProjectMilestone.project_id=pp.record_id 
         and is_external=0 
         and 
         (Actual_date is not null 
         or revised_date is not null 
         or proposed_date is not null) 
         ) AS internal_scheduled_milestones, 

        project_id 


       from 
        project pp 
        inner join v_ProjectMilestone on v_ProjectMilestone.project_id=pp.record_id 
) 



select 
Cast(Round(
(100.0*AllMilestones.all_actual_milestones)/ 
nullif(
(1.0*AllMilestones.all_milestones) 
,0) 
,0)as int) as percent_all_Actual_Milestones, 

Cast(Round(
(100.0*AllMilestones.all_Proposed_milestones)/ 
nullif(
(1.0*AllMilestones.all_milestones) 
,0) 
,0)as int) as percent_all_Proposed_Milestones, 

Cast(Round(
(100.0*AllMilestones.all_Revised_milestones)/ 
nullif(
(1.0*AllMilestones.all_milestones) 
,0) 
,0)as int) as percent_all_Revised_Milestones, 

Cast(Round(
(100.0*AllMilestones.all_scheduled_milestones)/ 
nullif(
(1.0*AllMilestones.all_milestones) 
,0) 
,0)as int) as percent_all_Scheduled_Milestones, 

Cast(Round(
(100.0*AllMilestones.External_actual_milestones)/ 
nullif(
(1.0*AllMilestones.External_milestones) 
,0) 
,0)as int) as percent_External_Actual_Milestones, 

Cast(Round(
(100.0*AllMilestones.External_Proposed_milestones)/ 
nullif(
(1.0*AllMilestones.External_milestones) 
,0) 
,0)as int) as percent_External_Proposed_Milestones, 

Cast(Round(
(100.0*AllMilestones.External_Revised_milestones)/ 
nullif(
(1.0*AllMilestones.External_milestones) 
,0) 
,0)as int) as percent_External_Revised_Milestones, 

Cast(Round(
(100.0*AllMilestones.External_scheduled_milestones)/ 
nullif(
(1.0*AllMilestones.External_milestones) 
,0) 
,0)as int) as percent_External_Scheduled_Milestones, 

Cast(Round(
(100.0*AllMilestones.Internal_actual_milestones)/ 
nullif(
(1.0*AllMilestones.Internal_milestones) 
,0) 
,0)as int) as percent_Internal_Actual_Milestones, 

Cast(Round(
(100.0*AllMilestones.Internal_Proposed_milestones)/ 
nullif(
(1.0*AllMilestones.Internal_milestones) 
,0) 
,0)as int) as percent_Internal_Proposed_Milestones, 

Cast(Round(
(100.0*AllMilestones.Internal_Revised_milestones)/ 
nullif(
(1.0*AllMilestones.Internal_milestones) 
,0) 
,0)as int) as percent_Internal_Revised_Milestones, 

Cast(Round(
(100.0*AllMilestones.Internal_scheduled_milestones)/ 
nullif(
(1.0*AllMilestones.Internal_milestones) 
,0) 
,0)as int) as percent_Internal_Scheduled_Milestones 
,project.*, 
AllMilestones.* 

from AllMilestones inner join project on project.record_id = AllMilestones.project_id 
+4

あなたは数十の代わりにこれを1回のクエリにすることができます。パフォーマンスが大幅に向上します。しかし、あなたの質問の性質とコードを考えれば、私はあなたがこれを新しい視点にすることを計画していると感じています。この新しいビューは他のビューを呼び出すので、ネストされたビューと呼ばれるものがあります。これにより、パフォーマンスの改善が完全に損なわれます。完全に論理的ですが、ネストされたビューはオプティマイザを混乱させる確実な方法です。この記事をご覧くださいhttps://www.simple-talk.com/sql/performance/the-seven-sins-against-tsql-performance/#seven –

+0

@SeanLangeこれは実際にはレポートになるでしょう。クエリとして実行されますが、それは頻繁に実行されませんが、私はそれを行うためのよりよい方法が必要であることを知っているので、非常に多くのサブクエリを作ることは嫌いです。 – gnarbarian

答えて

2

あなたのクエリは非常に複雑です。何度も同じテーブルを読まなければなりません。代わりに必要なのは、条件付き集約です。私はNULLIFを移動して、すべての行でそれを繰り返さないように、0で除算することを避けてWITH節に移動しました。

with allmilestones as 
(select 
    project_id, 
    nullif(count(*),0) as all_milestones, 

    count(case when 
      actual_date is not null 
      then 1 end) as all_actual_milestones, 

    count(case when 
       actual_date is null 
       and proposed_date is not null 
       and revised_date is null 
      then 1 end) as all_proposed_milestones, 
    count(case when 
       actual_date is null    
       and revised_date is not null 
      then 1 end) as all_revised_milestones 

    ,count(case when 
       (Actual_date is not null 
         or revised_date is not null 
         or proposed_date is not null) 
    then 1 end) as all_scheduled_milestones, 

    count(case when 
      is_external=1 
      then 1 end) as external_milestones, 
    count(case when 
      is_external=1 and 
      actual_date is not null 
      then 1 end) as external_actual_milestones, 

    count(case when 
    is_external=1 and 
       actual_date is null 
       and proposed_date is not null 
       and revised_date is null 
      then 1 end) as external_proposed_milestones, 
    count(case when 
    is_external=1 and 
       actual_date is null    
       and revised_date is not null 
      then 1 end) as external_revised_milestones 

    ,count(case when 
    is_external=1 and 
       (Actual_date is not null 
         or revised_date is not null 
         or proposed_date is not null) 
    then 1 end) as external_scheduled_milestones, 

    count(case when 
      is_external=0 
      then 1 end) as internal_milestones, 
    count(case when 
      is_external=0 and 
      actual_date is not null 
      then 1 end) as internal_actual_milestones, 

    count(case when 
    is_external=0 and 
       actual_date is null 
       and proposed_date is not null 
       and revised_date is null 
      then 1 end) as internal_proposed_milestones, 
    count(case when 
    is_external=0 and 
       actual_date is null    
       and revised_date is not null 
      then 1 end) as internal_revised_milestones 

    ,count(case when 
    is_external=0 and 
       (Actual_date is not null 
         or revised_date is not null 
         or proposed_date is not null) 
    then 1 end) as internal_scheduled_milestones 

    from v_projectmilestone 
    group by project_id 
) 
select 
    project_id, 
    cast(round(100.0 * all_actual_milestones/all_milestones, 0) as int) as percent_all_actual_milestones, 
    cast(round(100.0 * all_proposed_milestones/all_milestones, 0) as int) as percent_all_proposed_milestones, 
    cast(round(100.0 * all_revised_milestones/all_milestones, 0) as int) as percent_all_revised_milestones, 
    cast(round(100.0 * all_scheduled_milestones/all_milestones, 0) as int) as percent_all_scheduled_milestones , 

    cast(round(100.0 * external_actual_milestones/nullif(external_milestones,0), 0) as int) as percent_external_actual_milestones, 
    cast(round(100.0 * external_proposed_milestones/nullif(external_milestones,0), 0) as int) as percent_external_proposed_milestones, 
    cast(round(100.0 * external_revised_milestones/nullif(external_milestones,0), 0) as int) as percent_external_revised_milestones, 
    cast(round(100.0 * external_scheduled_milestones/nullif(external_milestones,0), 0) as int) as percent_external_scheduled_milestones, 

    cast(round(100.0 * internal_actual_milestones/nullif(internal_milestones,0), 0) as int) as percent_internal_actual_milestones, 
    cast(round(100.0 * internal_proposed_milestones/nullif(internal_milestones,0), 0) as int) as percent_internal_proposed_milestones, 
    cast(round(100.0 * internal_revised_milestones/nullif(internal_milestones,0), 0) as int) as percent_internal_revised_milestones, 
    cast(round(100.0 * internal_scheduled_milestones/nullif(internal_milestones,0), 0) as int) as percent_internal_scheduled_milestones 

from allmilestones; 

これは、あなたが一度だけのテーブルを読んだとして、それを取得ほど高速である必要があります。 1つのプロジェクトにつき1つの結果行が必要なのは間違いありません。

3

はい、すべてのサブクエリを、各サブクエリのWHERE句の条件をチェックするCASE式で置き換えることができます。例えば

、あなたの最初の二つのサブクエリはに置き換えられます。そうで

count(project_id) AS all_milestones, 
SUM(CASE WHEN Actual_date is not null THEN 1 ELSE 0 END) AS all_Actual_milestones, 

と。

パフォーマンスが向上するかどうかは、試してみる以外にはわからないことです。

+0

ありがとうございます。あなたは@ThorstenKettnerを3分遅らせましたが、彼の解決策はもう少し完成しました。私はあなたに両方の印をつけることができたらいいと思う。 – gnarbarian

関連する問題