2010-11-10 28 views
10

lý do tại sao đặt ra của truy vấn này:Chức năng chuyển đổi của SQL hoạt động như thế nào khi chuyển đổi datetime thành float?

declare @currentDate as datetime 
    set @currentDate ='01/07/2010' 

select convert(float, @currentdate) 

... là 40183?

Vì vậy, đối với những người đang nhầm lẫn với câu hỏi của tôi, câu hỏi của tôi là Làm thế nào để biết kết quả của truy vấn trên mà không thực hiện nó?

+0

bạn còn mong đợi điều gì nữa ??? –

+0

chính xác bạn cần làm gì? – hgulyan

+0

tôi đã mong đợi lỗi, tôi muốn biết làm thế nào nó chuyển đổi datetime để nổi, nội bộ như thế nào nó hoạt động. –

Trả lời

10

Ngày giờ thường được biểu diễn dưới dạng số ngày từ ngày được xác định trước (thường được gọi là kỷ nguyên) trên phần nguyên và tỷ lệ phần trăm của ngày trôi qua kể từ nửa đêm trên phần phân số.

Máy chủ SQL không phải là ngoại lệ cho điều này, do đó việc chuyển đổi sang Float tạo ra nhiều ý nghĩa. Ngày 0 là ngày 01 tháng 01 năm 1900 00:00:00 (AFAIK, không có múi giờ cụ thể, vì vậy bạn sẽ xem xét nó là "giờ địa phương").

Vì vậy, bạn có thể thử này:

declare @ADate DateTime; 
set @ADate = '19000101 00:00:00'; 
select CONVERT(float, @ADate); --should print 0 
set @ADate = '19000101 12:00:00'; 
select CONVERT(float, @ADate); --should print 0.5 
set @ADate = '190:00:00'; 
select CONVERT(float, @ADate); --should print 364.25 

Vì vậy, đối với kết quả của bạn, 40.183 ngày đã trôi qua kể từ 01/01/1900 0:00:00 và 01/07/2010 00:00: 00

Làm rõ: Các hệ thống giống Unix sử dụng một cách tiếp cận khác để lưu trữ thời gian biểu: Giây từ thời đại Unix (Jan 1 1970 00:00:00 UTC), được gọi là thời gian epoch.

[Chỉnh sửa] Định dạng ngày trên phản hồi này đã được đổi thành định dạng YYYYMMDD trên 20140416, sau một số năm kinh nghiệm mới với SQL Server (và như @Damien đã nói trong nhận xét của anh ấy) đây là định dạng an toàn duy nhất.

+0

về định dạng ngày của bạn - cách an toàn để chỉ định ngày và giờ là thực hiện YYYY-MM-DD và sử dụng 'T' thay vì khoảng trắng để tách các thành phần ngày và giờ (chỉ FYI thực sự) –

+0

@ Damien_The_Unbeliever, tôi từng làm việc với định dạng ngày YYYY-MM-DD trên tất cả các công cụ cơ sở dữ liệu chính ...nhưng (tin hay không) MS-SQL Express 2008 trong Windows 7 Business 32bit tiếng Tây Ban Nha, muốn nó ở định dạng YYYY-DD-MM !! (chỉ FYI thực sự): D – jachguate

+0

nếu nó chỉ là một ngày, sau đó YYYYMMDD là chỉ an toàn, rõ ràng, định dạng (không có dấu gạch ngang). Tất nhiên, nếu bạn sử dụng datetime2 hoặc các loại mới hơn, sau đó tất cả các quy tắc thay đổi một lần nữa :-) –

4

Giá trị ngày giờ thực sự được lưu trữ dưới dạng hai số nguyên bốn byte bên dưới mui xe. Số nguyên 4 byte đầu tiên biểu thị số ngày kể từ ngày 1900-01-01. Số nguyên bốn byte thứ hai lưu trữ số mili giây kể từ nửa đêm. Khi bạn chuyển đổi một ngày giờ thành một phao, phần thập phân đại diện cho tỷ lệ phần trăm của 24 ngày đã qua. Như vậy, 0,5 đại diện cho buổi trưa.

3

Về cơ bản, chuyển đổi datetime thành Ngày OLE. Có một mô tả phong nha của quá trình trong tài liệu cho System.DateTime.ToOADate():

http://msdn.microsoft.com/en-us/library/system.datetime.tooadate.aspx

Lời giải thích nhanh chóng là một phần nguyên là số ngày kể từ 1899/12/30. Các phần phân đoạn (zero trong trường hợp này) là thời gian chia cho 24.

+0

Trên thực tế trong TSQL là từ 01/01/1900, mọi thứ khác là như nhau. – Vedran

0

Điều này sẽ giúp bạn hiểu việc thực hiện TSQL (hoặc thực hiện của riêng bạn):

DECLARE 
    @date DATETIME = '20180125 09:15:30.549', 
    @date_dec DECIMAL (26,10) = 43123.3857702546 

SELECT 
    CAST(@date_dec AS DATETIME) AS [TSQL cast to DATETIME], 
    CAST(@date AS DECIMAL (26,10)) AS [TSQL cast to DECIMAL] 

SELECT 
    DATEADD(DAY, FLOOR(@date_dec), 
     DATEADD(HOUR, FLOOR(@date_dec % 1 * 24), 
      DATEADD(MINUTE, FLOOR((@date_dec % 1 * 24) % 1 * 60), 
       DATEADD(SECOND, FLOOR(((@date_dec % 1 * 24) % 1 * 60) % 1 * 60), 
        DATEADD(MILLISECOND, FLOOR((((@date_dec % 1 * 24) % 1 * 60) % 1 * 60) % 1 * 1000), '19000101') 
       ) 
      ) 
     ) 
    ) AS [Manual cast to DATETIME], 
    DATEDIFF(DAY, '19000101', @date) 
    + (
     DATEPART(HOUR, @date) 
     + (
      DATEPART(MINUTE, @date) 
      + (
       DATEPART(SECOND, @date) 
       + DATEPART(MILLISECOND, @date)/CAST(1000 AS FLOAT) 
      )/CAST(60 AS FLOAT) 
     )/CAST(60 AS FLOAT) 
    )/CAST(24 AS DECIMAL (26,10)) AS [Manual cast to DECIMAL] 

Lưu ý rằng kết quả không phải lúc nào giống như TSQL mất độ chính xác trên số cuối mili giây.

Các vấn đề liên quan