MSSQL-从money转换为datetime数据类型

MSSQL-从money转换为datetime数据类型,sql,sql-server,Sql,Sql Server,多亏了一些出色的应用程序设计,我才发现自己面对面地使用了一个真正的WTF——我支持的应用程序似乎将日期和时间输出到一个特定表中的两个单独的列中;日期作为datetime数据类型进入“日期”列,而时间作为money数据类型进入“时间”列,以分钟和秒为单位(例如,10:35:00为10.35英镑) 在对数据库进行查询时,我需要合并这两列,以便它作为一个完整的datetime列返回,但显然只是在执行 ...snip... CAST(au.[Date] as datetime) + CAST(au.[T

多亏了一些出色的应用程序设计,我才发现自己面对面地使用了一个真正的WTF——我支持的应用程序似乎将日期和时间输出到一个特定表中的两个单独的列中;日期作为
datetime
数据类型进入“日期”列,而时间作为
money
数据类型进入“时间”列,以分钟和秒为单位(例如,10:35:00为10.35英镑)

在对数据库进行查询时,我需要合并这两列,以便它作为一个完整的
datetime
列返回,但显然只是在执行

...snip...
CAST(au.[Date] as datetime) + CAST(au.[Time] AS datetime) as 'LastUpdateDate'
...snip...
。。。没有像我(奈维利)希望的那样起作用

我的前任遇到了这个问题,提出了一个。。。“创造性”解决方案:

MIN(DATEADD(HOUR,CAST(LEFT(CONVERT(VARCHAR(10),[time],0),CHARINDEX('.',CONVERT(VARCHAR(10),[time],0),0)-1) AS INT),DATEADD(MINUTE,CAST(RIGHT(CONVERT(VARCHAR(10),[time],0),LEN(CONVERT(VARCHAR(10),[time],0)) - CHARINDEX('.',CONVERT(VARCHAR(10),[time],0),0)) AS INT),[date]))) AS CreatedDateTime
与我的前任不同,我更愿意让这个解决方案尽可能简单。您认为可以通过以下方式将此列中的值转换为时间:

  • 把钱的价值抛给弦
  • 替换冒号的小数点
  • 将其作为datetime对象进行分析(以替换第一个代码块的
    强制转换(au.[Time]作为datetime)
    部分
  • 这可行吗?如果不可行,有人能帮忙吗

    编辑
    为了100%清楚,我无法更改列的基础数据类型,因为应用程序依赖的数据类型是
    money
    。这纯粹是为了让我编写的编写合理的应用程序能够真正读取完整的
    datetime
    值中的数据。

    刚刚了解了如何使用
    替换
    命令,它将按预期工作:

    CAST(au.[Date] as datetime) + CAST(REPLACE(CAST(au.[Time] AS varchar(5)),'.',':') AS datetime) as 'LastUpdateDate'
    
    现在输出
    2018-01-10 10:32:00.000
    ,而之前它提供了一些不正确的日期和时间值


    我想你可以按照@jeroemostert的建议进行数学上的转换——公平地说,我不是100%认为这个解决方案可能会对计算分钟数产生影响,并以这种方式进行转换,所以我也会尝试一下,以确保这一点。

    刚刚了解了如何使用
    REPLACE
    命令,它的工作原理如下预期:

    CAST(au.[Date] as datetime) + CAST(REPLACE(CAST(au.[Time] AS varchar(5)),'.',':') AS datetime) as 'LastUpdateDate'
    
    现在输出
    2018-01-10 10:32:00.000
    ,而之前它提供了一些不正确的日期和时间值


    我想你可以按照@Jeroemostert的建议进行数学转换——公平地说,我对这个解决方案可能对计算分钟数并以这种方式进行转换产生的性能影响不是100%,所以我也会尝试一下,以确保这一点。

    我更喜欢没有任何字符串铸件的算术转换

    MIN(
        DATEADD(
            MINUTE, 
            FLOOR(au.[Time]) * 60 + (au.[Time]-FLOOR(au.[Time])) * 100, 
            au.[Date])
    ) AS CreatedDateTime
    

    我更喜欢没有任何字符串转换的算术转换

    MIN(
        DATEADD(
            MINUTE, 
            FLOOR(au.[Time]) * 60 + (au.[Time]-FLOOR(au.[Time])) * 100, 
            au.[Date])
    ) AS CreatedDateTime
    

    如果无法直接将列更改为
    time
    ,则可以添加一层健全性:

    ALTER TABLE ... ADD SaneDate AS 
        DATEADD(MINUTE, FLOOR([Time]) * 60 + 100 * ([Time] - FLOOR([Time])), [Date])
    
    一个计算列,然后您可以继续使用它,而不是到处重复计算。如果不可能以任何方式更改表,您至少可以创建一个视图或表值函数来捕获此逻辑。(最好不是标量函数,尽管这更明显——它们在查询中的性能非常糟糕。)



    如果可能的话,我倾向于使用
    DATEADD
    而不是字符串操作,因为结果更容易预测。在这种情况下,没有真正的问题,因为将
    money
    转换为
    char(5)无论语言设置如何,
    都是完全可预测的,但仍然如此。

    如果无法直接将列更改为
    时间,则可以添加一层理智:

    ALTER TABLE ... ADD SaneDate AS 
        DATEADD(MINUTE, FLOOR([Time]) * 60 + 100 * ([Time] - FLOOR([Time])), [Date])
    
    一个计算列,然后您可以继续使用它,而不是到处重复计算。如果不可能以任何方式更改表,您至少可以创建一个视图或表值函数来捕获此逻辑。(最好不是标量函数,尽管这更明显——它们在查询中的性能非常糟糕。)



    如果可能的话,我倾向于使用
    DATEADD
    而不是字符串操作,因为结果更容易预测。在这种情况下,没有真正的问题,因为将
    money
    转换为
    char(5)无论语言设置如何,
    都是完全可预测的,但仍然是。

    如果没有数据外观的示例,您的问题毫无意义。将日期/时间值存储为
    money
    绝对是非标准的。时间单位是什么?
    money
    只是一种数字数据类型,因此您可以将其转换为
    十进制
    >你需要知道你是在增加秒、毫秒还是别的什么。哦,等等,他们是把13:56存储为13.56吗?那太好笑了。
    FLOOR($13.56)*60+100*($13.56-FLOOR($13.56))
    是以分钟为单位的值。大家好!为了澄清这一点,时间存储为MM.ss这是一个很好的设计:),很好,您正在对它进行排序。我在类似的情况下尝试了这一点
    选择cast(cast(getdate()as date)as datetime)+cast(cast(替换('10.35',',':'))as time)as datetime)
    如果没有数据外观示例,您的问题就毫无意义。将日期/时间值存储为
    货币
    肯定是不标准的。时间单位是什么?
    货币
    只是一种数字数据类型,因此您可以将其转换为所需精度的
    十进制
    ,然后将其转换为
    日期添加
    ——但您不需要这样做ed想知道你是在增加秒、毫秒还是别的什么。哦,等等,他们是不是在存储,比如说,
    13:56
    13.56
    ?那太好笑了。
    FLOOR($13.56)*60+100*($13.56-FLOOR($13.56)-FLOOR($13.56))
    是以分钟为单位的值。嗨,两者都好!为了澄清一下,时间存储为MM.ss这是一个很好的设计:),很好,您正在对它进行整理。我在类似的情况下尝试了这一点
    select cast(cast(getdate()as date)as dat)