有没有办法将此with子句中的子查询统一到一个查询中?它会提高性能吗?

时间:2016-09-28 18:50:51

标签: sql sql-server

架构信息:

v_ProjectMilestone通过project_id

引用项目

里程碑可以是内部的也可以是外部的(milestone.is_external = 1)

里程碑有三个我们关心的日期列(实际,修订或建议)

他们希望能够看到具有每个日期值的里程碑百分比,以及所有这些日期在内部和外部里程碑之间划分,以及每个项目的组合。

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

2 个答案:

答案 0 :(得分:3)

是的,您可以使用CASE表达式替换所有子查询,该表达式检查每个子查询的WHERE子句中的条件。

例如,您的前两个子查询将替换为:

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

等等。

至于它是否会有更好的表现,除了尝试之外,我无法确定除此之外。

答案 1 :(得分:2)

您的查询非常复杂;你必须一遍又一遍地读同一张桌子。你需要的是条件聚合。我移动NULLIF以避免将零除以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;

这应该尽可能快,因为你只读了一次表。我希望我说得对,你想要每个项目一个结果行。