一位同事想出了一个内部ID,该ID组合了多个不同的标识符,所有标识符都进行了位移。
我正在尝试使用T-SQL从此BIGINT
中获取“ TotalSeconds”。我能想到的唯一方法是对将21(?)转换为50的数字进行“与”运算,然后将其转换回INT,然后使用dateadd来获取时间。
特别是这部分:
StartUTC = new DateTime(BaseYear, 1, 1).ToUniversalTime();
TimeSpan timeSpan = DateTime.UtcNow - StartUTC;
...(one of the identifiers)
+ (((ulong) timeSpan.TotalSeconds % 1073741824L) << 20) + // 30 bits.
...(another of the identifiers)
注意:SQL Server无法正常处理无符号整数。
除以2的幂等于右移,例如C#中的Foo >> 3
在TSQL中为Foo / Power( 2, 3 )
。它适用于最大64位的整数类型。
按位与(&
)和模量(&
)可以使用2的幂,但不可互换。要提取五个最低有效位,可以使用%
或%
。第一个返回除以0x20后的余数,第二个返回使用掩码0x1F掩盖不需要的位。需要牢记两个重要区别:(1)按位与限制为32位值,而模数最多可以为64位;(2)如果原始值为负,则结果的符号不同:
Foo % Power( 2, 5 )
全部放在一起,您可以通过将原始值除以将感兴趣的位移到最低有效位,然后从掩码中将Foo & ( Power( 2, 5 ) - 1 )
位的位域select 10 % 4 as ModPos, 10 & 3 as AndPos, -10 % 4 as ModNeg, -10 & 3 as AndNeg;
位从FieldWidth
值的最低位开始提取,关闭所有不需要的位:
FieldOffset
原始问题涉及将结果BigInt
转换为( OriginalValue / Power( 2, FieldOffset) ) % Power( 2, FieldWidth )
。最接近的TSQL数据类型为NumberOfSeconds
,并且它被限制为小于24小时(即一天中的时间)的值。如果该值在TimeSpan
的范围内,则可以将其转换为:
Time