我想转换 Netezza
TO_TIMESTAMP(TO_CHAR(POL.PERIOD_FROM_DATE, 'FM99999999999999999'), 'YYYYMMDDHH24MISSMS') AS EFFECTIVE_DATE
到 SQL Server 函数以将其包含在 IBM Cognos Framework Manager 中
要求输出:
2023-02-24 00:00:00.0
有人可以帮我吗?
看起来
PERIOD_FROM_DATE
是一个 numeric(17,0) 列,每个数字匹配日期时间值中的位置,精确到第 1000 秒。
这是一个糟糕的模式选择,但我知道你在这里可能没有发言权。此外,Oracle 代码以最糟糕的方式处理这个问题。由于文化/国际化问题,字符串和数字或日期值之间的转换是您可以采用的最慢和最容易出错的方法。
假设模式是一成不变的(但实际上:如果可以的话改变它),为了更好地解决 SQL Server 的这个问题,我们将把它分成两部分:
DateTime
值注意:您通常好多了只需返回原始日期时间,并让客户端代码或工具处理格式。这使您可以完全跳过第二部分,这就是 Oracle 代码所做的。您看到特定的字符串格式是工具的意外,因为从 Oracle 返回的结果是 binary 而根本不是人类可读的值。
再次,我假设你无法控制这个要求,但在你有能力的情况下,你应该推动 fix 这个(因为当前的设计确实是 broken)。
DATETIMEFROMPARTS()
方法:
DATETIMEFROMPARTS(
cast(POL.PERIOD_FROM_DATE/10000000000000 as int), -- year
cast(POL.PERIOD_FROM_DATE/100000000000 % 100 as int), -- month
cast(POL.PERIOD_FROM_DATE/1000000000 % 100 as int), -- day
cast(POL.PERIOD_FROM_DATE/10000000 % 100 as int), -- hour
cast(POL.PERIOD_FROM_DATE/100000 % 100 as int), -- minute
cast(POL.PERIOD_FROM_DATE/1000 % 100 as int), -- second
cast(POL.PERIOD_FROM_DATE % 1000 as int) -- milliseconds
)
看起来你可能只想要毫秒的第一个数字。如果是这样,您可以相应地调整该部分,因为我没有足够的信息来知道是舍入还是截断余数。
这可能看起来像很多代码和对列的单独访问,但我向您保证,它应该比字符串替代方案更快、更可靠,而且差距不小。它仍然假设数据是一致存储的。
一旦你有了这个
DateTime
值,你就可以使用 CONVERT()
或 FORMAT()
获得格式化的字符串,如果可能,前者是首选。不幸的是,没有一种内置格式使用带有小数秒的单个数字,因此您需要这样做:
FORMAT(DATETIMEFROMPARTS(
cast(POL.PERIOD_FROM_DATE/10000000000000 as int), -- year
cast(POL.PERIOD_FROM_DATE/100000000000 % 100 as int), -- month
cast(POL.PERIOD_FROM_DATE/1000000000 % 100 as int), -- day
cast(POL.PERIOD_FROM_DATE/10000000 % 100 as int), -- hour
cast(POL.PERIOD_FROM_DATE/100000 % 100 as int), -- minute
cast(POL.PERIOD_FROM_DATE/1000 % 100 as int), -- second
cast(POL.PERIOD_FROM_DATE % 1000 as int) -- milliseconds
), 'yyyy-MM-dd HH:mm:ss.f')
在这里看到它的工作:
You should use the time to convert your number column zto a proper datetime and only use that in future.
每次转换都需要很多时间,所以日期应始终存储为此类数据类型
declare @input As numeric(17,0) = 20230324121023123
select
CONVERT(DATETIME,
CAST(
Substring(cast(@input as varchar), 0,9) + ' '
+ Substring(cast(@input as varchar),09,2)
+ ':' + Substring(cast(@input as varchar), 11,2)
+ ':' + Substring(cast(@input as varchar), 13,2)
+ ':' + Substring(cast(@input as varchar), 15,3)
as datetime),120) dat
达 |
---|
2023-03-24 12:10:23.123 |
=> select 20230324121023123, TO_CHAR(20230324121023123,'9999-99-99 99:99:99"."999');
?COLUMN? | TO_CHAR
-------------------+--------------------------
20230324121023123 | 2023-03-24 12:10:23.123