1

我有下面的查询,我把它放在一起,它运行得很糟糕(我相信你可以看到)。

我很确定这与我转换日期时间的方式有关,以便我可以参考昨天的数据。

dtInteractionLocalStartTime 是一个日期时间字段,我希望它显示为 mm/dd/yyyy 而不是 yyyy-mm-dd hh:mm:ss.sss

关于如何优化它的任何想法?我已经花了过去 2 天,我无法弄清楚。

这是我的查询:

SELECT TOP 100 PERCENT
       Date ,
       CONVERT(varchar, VDN) AS VDN ,
       COUNT(*) AS Calls ,
       Avaya
FROM ( SELECT DISTINCT TOP 100 PERCENT
              CONVERT(varchar,dtInteractionLocalStartTime,101) AS Date ,
              vcVectorNumber AS VDN ,
              iCompoundID ,
              'CM03' AS Avaya
       FROM NICEHUB3ADTM.nice_dw.dbo.vwNiceDBKitInteraction AS i
       WHERE CONVERT(varchar(10) , dtInteractionLocalStartTime,101) = CONVERT(varchar(10),GETDATE()-1,101)
         AND iMediaTypesId = 2
         AND tiCallDirectionTypeID = 1
         AND tiInteractionTypeID = 2
         AND iInteractionOpenReasonID & 16 = 0
         AND iInteractionOpenReasonID & 4 = 0
         AND iInteractionID NOT IN ( SELECT iInteractionID
                                     FROM NICEHUB3ADTM.nice_dw.dbo.vwException AS e
                                     WHERE i.iInteractionID = iInteractionID
                                       AND iExceptionTypeID IN (37, 12, 12310)
                                   )
     ) AS derivedtbl_1
GROUP BY Date ,
         CONVERT(varchar,VDN) ,
         Avaya
ORDER BY Date ,
         VDN
4

2 回答 2

5

如果您想要的只是日期而不是日期时间,只需使用:

CAST(yourDate AS DATE)

几乎可以肯定,任何格式化都应该在 sql 之外完成,因为 sql 几乎没有针对这种事情进行优化,并且当您的视图逻辑以您的方式进入模型时,最终会完全违反关注点分离。

至少,将子查询中的转换调用更改为上面的转换,并仅将单个转换添加到最外层的选择(在 group by 之后)。如果您目前有能力在其他地方重构逻辑,我仍然会完全避免它。

于 2013-08-08T22:20:43.320 回答
4

一些想法(因为“运行糟糕”不是一个很好的问题陈述):

  • 摆脱top 100 percent, 全面。这表示返回所有内容,这是 SQL 默认执行的操作。

  • 使用的select distinct代码气味。这强烈表明您提出了错误或不正确的问题,或者您不了解查询中涉及的实体之间关系的基数。SQL 处理集合。根据定义,集合是唯一的,所以如果你必须强制唯一,你几乎肯定做错了什么。

  • 您的派生表不是必需的

  • 您正在对同一列进行两个位旋转测试。可以组合的。

  • 您正在执行相关子查询并使用not in (...)而不是not exists (...)

  • 您正在将 vcVectorNumber 转换为 varchar。不知道它的数据类型,这似乎无关紧要:让应用程序处理转换为字符串。

  • datetime在比较列的同时转换列。这会将其变成一个表达式,并且该表达式不能使用索引,因此您会阻止查询优化器使用任何合适的索引。不要那样做。datetime如果可能的话,以一种不需要那种跳跃的方式测试列:between是你的朋友。

这就是我重构您的查询的方式。我相信这会产生相同的结果:

select convert(date,i.dtInteractionLocalStartTime) as Date  ,
       i.vcVectorNumber                            as VDN   ,
       count(distinct i.iCompoundId)               as Calls ,
       'CM03'                                      as Avaya
from NICEHUB3ADTM.nice_dw.dbo.vwNiceDBKitInteraction i
where i.dtInteractionLocalStartTime between dateadd(day ,-1 ,convert(datetime,convert(date,getdate()))) -- yesterday, midnight/start-of-day
                                        and dateadd(ms  ,-3 ,convert(datetime,convert(date,getdate()))) -- yesterday, end-of-day
  and i.iMediaTypesId                     = 2
  and i.tiCallDirectionTypeID             = 1
  and i.tiInteractionTypeID               = 2
  and i.iInteractionOpenReasonId & 0x0014 = 0 -- ( 16|4 is 20, 0x0014)
  and not exists ( select *
                   from NICEHUB3ADTM.nice_dw.dbo.vwException e
                   where e.iInteractionID = i.iInteractionID
                     and e.iExceptionTypeID IN ( 37 , 12 , 12310 )
                 )
group by convert(date,i.dtInteractionLocalStartTime) ,
         i.vcVectorNumber
order by convert(date,i.dtInteractionLocalStartTime) ,
         i.vcVectorNumber

最后一个观察:由 4 部分组成的表名称表明可能使用跨服务器查询或链接服务器。如果是这样(根据我的经验),那可能是一项昂贵的操作。首先将远程数据吸入本地临时表有助于提高性能。

于 2013-08-08T22:52:24.083 回答