分解成更小的查询

Posted

技术标签:

【中文标题】分解成更小的查询【英文标题】:break down into smaller queries 【发布时间】:2018-08-06 08:22:18 【问题描述】:

在上周这里的人们的大力帮助下,我能够完成一个相当复杂的请求。但是现在我被要求(或建议)将查询分解为多个简单的查询,而不是复杂的查询。 当前查询是:

select i.IncidentNumber,
   r.unit_type, 
      r.unit,
      r.arv_dttm as Onscene_time,
   r.clr_dttm as Clear_time,
      datediff(minute, arv_time, clr_time) as time_diff
from (select CADIncidentNumber, 
         unit_type, unit, 
                  arv_dttm, 
                  clr_dttm,
                 arv_time,
                 clr_time,
         sum(case when unit_type = 'Ambulance' then 1 else 0 end) over (partition by CADIncidentNumber) as ambulance_cnt,
         count(*) over (partition by CADIncidentNumber) as cnt
  from dw_prod.dbo.vw_unit_response 
  where CallTypeGrp2 = 'ALS' 
     and unit_type in ('Ambulance', 'Medic', 'Paramedic Engine', 'Paramedic Truck', 'Paramedic Tower', 'Paramedic Rescue Engine', 'Paramedic Brush Engine', 'Paramedic Rescue Squad')
  and DATEDIFF(DAY, arv_dttm,GETDATE()) < 8 
     and datediff(minute, arv_time, clr_time) > 5 
     ) r
left join INC_UnitInformation u on u.IncidentNumber = r.CADIncidentNumber
left join INC_Incident i on i.IncidentNumber = r.CADIncidentNumber
where ambulance_cnt > 0 and cnt >= 2
and not (u.PrimaryRoleOfUnit = 411000 or u.PrimaryRoleOfUnit = 411005) 
and r.unit_type not like 'Ambulance'
group by i.IncidentNumber, r.unit_type, r.unit, r.arv_dttm, r.clr_dttm, 
r.arv_time,r.clr_time
having COUNT(i.IncidentID) < 2
and sum(case when u.EMSUnitNumber like 'A%' then 1 else 0 end) > 0
order by r.arv_dttm

查询的结果需要在其值中包含“Ambulance”,它现在就是这样做的。查询结果没有问题。我只是想看看这个复杂的查询是否可以分解成多个粘合在一起的较小查询。除了计算和确保救护车值包含在结果中的功能外,我认为这并不复杂,但我不知道....

谢谢!

【问题讨论】:

为什么要将其分解为多个查询?只是为了这样做而这样做有点愚蠢。您被要求这样做一定是有原因的。 正确格式化的 SQL 更容易阅读和理解。 原因是为了避免潜在的性能问题和资源阻塞。虽然当前查询运行并吐出结果并不需要很长时间,但是是的。 所以您打算使用非标准技术将其分解为多个查询来处理不存在的性能问题?这是一种不好的做法,称为过早优化。这不是一件好事。 我同意,如果它运行正确且快速,它看起来还不错。别管它:) 【参考方案1】:

我认为将您的查询分解为多个(两个)查询的最明显方法是获取您的派生表:

from (select CADIncidentNumber, 
         unit_type, unit, 
                  arv_dttm, 
                  clr_dttm,
                 arv_time,
                 clr_time,
         sum(case when unit_type = 'Ambulance' then 1 else 0 end) over (partition by CADIncidentNumber) as ambulance_cnt,
         count(*) over (partition by CADIncidentNumber) as cnt
  from dw_prod.dbo.vw_unit_response 
  where CallTypeGrp2 = 'ALS' 
     and unit_type in ('Ambulance', 'Medic', 'Paramedic Engine', 'Paramedic Truck', 'Paramedic Tower', 'Paramedic Rescue Engine', 'Paramedic Brush Engine', 'Paramedic Rescue Squad')
  and DATEDIFF(DAY, arv_dttm,GETDATE()) < 8 
     and datediff(minute, arv_time, clr_time) > 5 
     ) r

并单独使用它来填充表变量。然后用主查询中的表变量替换它。

【讨论】:

【参考方案2】:

希望,我正确理解了您的问题。

建议您为内部查询创建一个视图。

*为您的视图使用适当的名称。

create view view_1 select CADIncidentNumber, 
         unit_type, unit, 
                  arv_dttm, 
                  clr_dttm,
                 arv_time,
                 clr_time,
         sum(case when unit_type = 'Ambulance' then 1 else 0 end) over (partition by CADIncidentNumber) as ambulance_cnt,
         count(*) over (partition by CADIncidentNumber) as cnt
  from dw_prod.dbo.vw_unit_response 
  where CallTypeGrp2 = 'ALS' 
     and unit_type in ('Ambulance', 'Medic', 'Paramedic Engine', 'Paramedic Truck', 'Paramedic Tower', 'Paramedic Rescue Engine', 'Paramedic Brush Engine', 'Paramedic Rescue Squad')
  and DATEDIFF(DAY, arv_dttm,GETDATE()) < 8 
     and datediff(minute, arv_time, clr_time) > 5 ;

select i.IncidentNumber,
   r.unit_type, 
      r.unit,
      r.arv_dttm as Onscene_time,
   r.clr_dttm as Clear_time,
      datediff(minute, arv_time, clr_time) as time_diff
from view_1 r
left join INC_UnitInformation u on u.IncidentNumber = r.CADIncidentNumber
left join INC_Incident i on i.IncidentNumber = r.CADIncidentNumber
where ambulance_cnt > 0 and cnt >= 2
and not (u.PrimaryRoleOfUnit = 411000 or u.PrimaryRoleOfUnit = 411005) 
and r.unit_type not like 'Ambulance'
group by i.IncidentNumber, r.unit_type, r.unit, r.arv_dttm, r.clr_dttm, 
r.arv_time,r.clr_time
having COUNT(i.IncidentID) < 2
and sum(case when u.EMSUnitNumber like 'A%' then 1 else 0 end) > 0
order by r.arv_dttm

【讨论】:

以上是关于分解成更小的查询的主要内容,如果未能解决你的问题,请参考以下文章

如何将文本文件分解成更小的块(在 Unix 上使用 C++)?

有没有办法拆分/分解 Gradle 构建的常见部分

分治思想 : 并归排序与其时间复杂度

如果我想将视图分解为更小的子视图,我应该在 ASP.NET MVC 中创建啥项目?

面向对象相关概述

PHP面向对象所学部分