有没有更好的方法将SQL日期时间从hh:mm:ss转换为hhmmss?

Joh*_* J. 2 sql t-sql sql-server

我必须编写一个SQL视图,它将日期时间列的时间部分作为字符串以hhmmss格式返回(显然SAP BW不理解hh:mm:ss).

这段代码是SAP推荐的方法,但我认为必须有一种更好,更优雅的方法来实现这一目标

TIME = case len(convert(varchar(2), datepart(hh, timecolumn)))
             when 1 then       /* Hour Part of TIMES */
               case convert(varchar(2), datepart(hh, timecolumn))
                 when '0' then '24'    /* Map 00 to 24 ( TIMES ) */
                 else '0' + convert(varchar(1), datepart(hh, timecolumn))
               end
            else convert(varchar(2), datepart(hh, timecolumn))
            end
         + case len(convert(varchar(2), datepart(mi, timecolumn)))
              when 1 then '0' + convert(varchar(1), datepart(mi, timecolumn))
              else convert(varchar(2), datepart(mi, timecolumn))
           end
         + case len(convert(varchar(2), datepart(ss, timecolumn)))
              when 1 then '0' + convert(varchar(1), datepart(ss, timecolumn))
              else convert(varchar(2), datepart(ss, timecolumn))
           end
Run Code Online (Sandbox Code Playgroud)

这样就完成了预期的结果,21:10:45显示为211045.

我喜欢更紧凑,更易读的东西,但到目前为止我还没有想出任何有效的东西.

spe*_*593 5

注意:

问题是该列是数据类型DATETIME,而不是较新的(SQL Server 2008) TIME数据类型.

回答:

  REPLACE(CONVERT(VARCHAR(8),timecolumn,8),':','')
Run Code Online (Sandbox Code Playgroud)

让我们打开它.

首先,CONVERT将日期时间的时间部分格式化为varchar,格式为'hh:mi:ss'(24小时制),格式样式值为8.

接下来,该REPLACE函数删除冒号,以格式获取varchar 'hhmiss'.

这应该足以以您需要的格式获取可用的字符串.


后续问题

(OP问题问)

内联表达式比用户定义的函数更快/更少服务器密集型吗?

快速回答是肯定的.更长的答案是:它取决于几个因素,你真的需要衡量性能,以确定这是否真实.

我创建并执行了一个基本的测试用例:

    -- sample table
    create table tmp.dummy_datetimes (c1 datetime)

    -- populate with a row for every minute between two dates
    insert into tmp.dummy_datetimes
    select * from udfDateTimes('2007-01-01','2009-01-01',1,'minute')

    (1052641 row(s) affected)

    -- verify table contents
    select min(c1) as _max
         , max(c1) as _min
         , count(1) as _cnt
      from tmp.dummy_datetimes

    _cnt    _min                    _max
    ------- ----------------------- -----------------------
    1052641 2007-01-01 00:00:00.000 2009-01-01 00:00:00.000

(注意,udfDateTimes函数以指定的时间间隔返回两个日期时间值之间的所有日期时间值的集合.在这种情况下,我每隔一分钟用行填充虚拟表两年.这是一百万的订单(2x365x24x60) )行.

现在,用户定义的函数使用相同的语法执行与内联表达式相同的转换:

    CREATE FUNCTION [tmp].[udfStrippedTime] (@ad DATETIME)
    RETURNS VARCHAR(6)
    BEGIN
    -- Purpose: format time portion of datetime argument to 'hhmiss'
    -- (for performance comparison to equivalent inline expression)
    -- Modified:
    -- 28-MAY-2009 spencer7593

       RETURN replace(convert(varchar(8),@ad,8),':','')

    END

注意:我知道函数未定义为DETERMINISTIC.(我认为这需要使用模式绑定和其他一些声明来声明函数,比如PRAGMA所需的Oracle.)但由于每个日期时间值在表中都是唯一的,因此无关紧要.该函数将必须为每个不同的值执行,即使它被正确声明为DETERMINISTIC.

我不是这里的SQL Server'用户定义函数'大师,所以我可能会遗漏一些其他无意中并且不必要地减慢函数速度的东西.

好的.

因此,对于测试,我交替地运行这些查询中的每一个,首先是一个,然后是另一个,一遍又一遍地.第一次运行的经过时间与随后的运行一致.(通常情况并非如此,我们希望省去第一次运行的时间.)SQL Server Management Studio将查询已用时间报告到最接近的秒,格式为hh:mi:ss,这就是我在此报告的内容.

    -- elapsed times for inline expression
    select replace(convert(varchar(8),c1,8),':','') from tmp.dummy_datetimes

    00:00:10
    00:00:11
    00:00:10

    -- elapsed times for equivalent user defined function
    select tmp.udfStrippedTime(c1) from tmp.dummy_datetimes

    00:00:15
    00:00:15
    00:00:15

对于此测试用例,我们观察到用户定义的函数比等效的内联表达式慢45%.

HTH