SQL将Datetime转换为varchar10并减去1天

时间:2013-08-08 22:08:46

标签: sql sql-server tsql sql-server-2008-r2

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

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

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

有关如何优化此问题的任何想法?我花了两天时间才弄清楚。

这是我的问题:

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

2 个答案:

答案 0 :(得分:5)

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

CAST(yourDate AS DATE)

任何完成的格式化几乎都应该在sql之外完成,因为sql几乎没有针对这类事情进行优化,并且当你的视图逻辑工作进入模型时,最终会破坏关注点。

至少,将子查询中的转换调用更改为上面的转换,并且只将一个转换添加到最外面的选择(在分组之后)。如果你有能力在其他地方重构逻辑,我仍然会完全避免它。

答案 1 :(得分: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部分表名称表示可能使用跨服务器查询或链接服务器。如果是这样(根据我的经验),这可能是一项昂贵的操作。首先将远程数据吸收到本地临时表可以帮助提高性能。