有没有更好的方法将SQLDateTime从hh:mm:ss转换为hhmmss?

有没有更好的方法将SQLDateTime从hh:mm:ss转换为hhmmss?,sql,sql-server,tsql,Sql,Sql Server,Tsql,我必须编写一个SQL视图,以hhmmss格式返回datetime列的时间部分,显然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

我必须编写一个SQL视图,以hhmmss格式返回datetime列的时间部分,显然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
这实现了所需的结果,21:10:45显示为211045


我想要更简洁易读的东西,但到目前为止,我还没有找到任何可行的方法。

您可以使用用户定义的函数,如:

create FUNCTION [dbo].[udfStrippedTime]
(
    @dt datetime
)
RETURNS varchar(32)
AS
BEGIN
    declare @t varchar(32)
    set @t = convert( varchar(32), @dt, 108 )
    set @t = left(@t,2) + substring(@t,4,2)

    RETURN @t
END
然后

秒的逻辑留作读者练习

编辑2:更新以处理0->24转换,以及较短的版本:

select replace(left(replace(convert(char,getdate(),8),':',''),2),'00','24') + right(replace(convert(char,getdate(),8),':',''),4)

回到稍长的版本:

选择替换'2009-05-27 12:49:19',':',
2009-05-27 124919这里有个问题。是否需要在Db服务器上进行格式化?服务器本身实际上只关心数据,并针对存储数据进行了优化。从严格的学术意义上讲,查看数据通常是数据库上面的hte层的责任,现实世界有点混乱

例如,如果要将结果输出到绑定到GridControl的ASP.NET页面,则在绑定到列时只需指定DataFormattingString。如果使用c将其写入文本文件,则在提取数据时,只需将格式字符串传递给.ToString函数


如果您需要将它具体地放在DbServer上,那么几乎所有的解决方案都会很混乱,因为您需要的时间格式虽然紧凑且符合逻辑,但不是服务器可以识别的时间格式,因此您需要将其作为字符串进行操作

这将处理00->24转换

SELECT CASE WHEN DATEPART(hh,timecolumn) = 0 
    THEN  '24' + SUBSTRING(REPLACE(CONVERT(varchar(8),timecolumn, 108),':',''),3,4)
    ELSE REPLACE(CONVERT(varchar(8),timecolumn, 108),':','') END

选择replaceconvertvarchar15,datetimefield,108':', 从表中

注意:

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

答复:

让我们把它打开

首先,将datetime的时间部分格式转换为varchar,格式为“hh:mi:ss”24小时时钟,格式样式值为8

接下来,REPLACE函数删除冒号,以获取格式为“hhmiss”的varchar

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

后续问题

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 对于这个测试用例,我们观察到用户定义的函数比等效的内联表达式慢45%


HTH

00:02:03->240203-代码不受格式的影响,因为它使用datepart返回整数。我真的不知道为什么SAP BW希望午夜由24而不是00表示,这对我来说毫无意义,但是,SAP也不是很容易理解的。经过大量的讨论和意见的反复改变,我们的系统不需要使用00->24的演员阵容。想想看,不必做疯狂的00->24转换是一种解脱。有些情况下,格式化最好在服务器上完成。这里的讨论:是的,我被告知格式化需要在DB服务器上进行,所以这就是他们得到的结果。我无法想象为什么一个系统会将午夜解释为24小时而不是0小时。但是如果真的是这样,这是你的钱的答案。好答案,我会这样标记它,除非在SAP管理员方面有很多冲突的信息,我被告知00->24 cast是不必要的,所以只使用functionright'24'+cast更容易。。。无法正常工作-请尝试01:02:03-再试一次:-@OrbMan:看起来不错。如果您在第一次转换的数据类型上指定长度为2,那么您将只剩下两位数的小时。知道了这一点,就不需要LEFT函数,也不需要REPLACE来删除冒号。这应该会进一步缩短表达式。@AlexK:该表达式去掉了字符串中的冒号,但它不会只返回DATETIME表达式的时间部分“hhmiss”,也不会将00小时替换为24小时。为了便于重复使用,我选择了这个答案,如果再让我处理这样的案子。顺便说一句,这是完整的一行:set@t=left@t,2 + substring@t,4,2 + substring@t,7,2只是为了澄清一下,请参阅我对以下问题的第二条评论:为什么我在没有00->24 cast的情况下使用此选项。REPLACECONVERTVARCHAR8,timecolumn,8',:',斯宾塞:这会更快/更少占用服务器吗?约翰,简短的回答是肯定的,内联表达式将比等效的用户定义函数更快。答案当然更长 这取决于很多因素,我们需要运行一个测试用例来演示性能差异。我已经完成了,创建并运行了测试用例,并将结果包含在我对您的问题的回答中。对于我运行的测试用例,用户定义的函数比内联表达式慢45%。测试用例的详细信息再次出现在我的答案中。嗯
  REPLACE(CONVERT(VARCHAR(8),timecolumn,8),':','')
-- 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 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 -- 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