Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

DATEDIFF ở định dạng HH:MM:SS

Bạn không nên chuyển đổi sang time - nó có nghĩa là để lưu trữ một điểm trong thời gian trên một đồng hồ 24 giờ, không phải là thời lượng hoặc khoảng thời gian (ngay cả một thời điểm bị giới hạn ở mức <24 giờ, điều này rõ ràng là dữ liệu của bạn không). Thay vào đó, bạn có thể lấy ngày tháng trong khoảng thời gian nhỏ nhất cần thiết (trong trường hợp của bạn là giây), sau đó thực hiện một số thao tác toán học và chuỗi để trình bày nó ở định dạng đầu ra bạn cần (cũng có thể tốt hơn nếu trả lại giây cho ứng dụng hoặc công cụ báo cáo và yêu cầu nó thực hiện công việc này).

DECLARE @d TABLE
(
  id INT IDENTITY(1,1), 
  StartDateTime DATETIME, 
  EndDateTime DATETIME
);

INSERT @d(StartDateTime, EndDateTime) VALUES 
(DATEADD(DAY, -2, GETDATE()), DATEADD(MINUTE, 15, GETDATE())),
(GETDATE()                  , DATEADD(MINUTE, 22, GETDATE())),
(DATEADD(DAY, -1, GETDATE()), DATEADD(MINUTE,  5, GETDATE())),
(DATEADD(DAY, -4, GETDATE()), DATEADD(SECOND, 14, GETDATE()));

;WITH x AS (SELECT id, StartDateTime, EndDateTime, 
  d = DATEDIFF(SECOND, StartDateTime, EndDateTime),
  a = AVG(DATEDIFF(SECOND, StartDateTime, EndDateTime)) OVER()
  FROM @d
)
SELECT id, StartDateTime, EndDateTime,
  [delta_HH:MM:SS] = CONVERT(VARCHAR(5), d/60/60)
  + ':' + RIGHT('0' + CONVERT(VARCHAR(2), d/60%60), 2)
  + ':' + RIGHT('0' + CONVERT(VARCHAR(2), d % 60), 2),
  [avg_HH:MM:SS] = CONVERT(VARCHAR(5), a/60/60)
  + ':' + RIGHT('0' + CONVERT(VARCHAR(2), a/60%60), 2)
  + ':' + RIGHT('0' + CONVERT(VARCHAR(2), a % 60), 2)
FROM x;

Kết quả:

id  StartDateTime        EndDateTime          delta_HH:MM:SS  avg_HH:MM:SS
--  -------------------  -------------------  --------------  ------------
1   2013-01-19 14:24:46  2013-01-21 14:39:46  48:15:00        42:10:33
2   2013-01-21 14:24:46  2013-01-21 14:46:46   0:22:00        42:10:33
3   2013-01-20 14:24:46  2013-01-21 14:29:46  24:05:00        42:10:33
4   2013-01-17 14:24:46  2013-01-21 14:25:00  96:00:14        42:10:33

Đây không chính xác là những gì bạn yêu cầu, vì nó sẽ không chỉ hiển thị MM:SS cho delta <1 giờ. Bạn có thể điều chỉnh điều đó bằng một CASE đơn giản biểu thức:

;WITH x AS (SELECT id, StartDateTime, EndDateTime, 
  d = DATEDIFF(SECOND, StartDateTime, EndDateTime),
  a = AVG(DATEDIFF(SECOND, StartDateTime, EndDateTime)) OVER()
  FROM @d
)
SELECT id, StartDateTime, EndDateTime,
  [delta_HH:MM:SS] = CASE WHEN d >= 3600 THEN 
    CONVERT(VARCHAR(5), d/60/60) + ':' ELSE '' END
  + RIGHT('0' + CONVERT(VARCHAR(2), d/60%60), 2)
  + ':' + RIGHT('0' + CONVERT(VARCHAR(2), d % 60), 2),
  [avg_HH:MM:SS] = CASE WHEN a >= 3600 THEN 
    CONVERT(VARCHAR(5), a/60/60) + ':' ELSE '' END
  + RIGHT('0' + CONVERT(VARCHAR(2), a/60%60), 2)
  + ':' + RIGHT('0' + CONVERT(VARCHAR(2), a % 60), 2)
FROM x;

Truy vấn này thay đổi cột delta ở hàng thứ 2 trong kết quả ở trên từ 0:22:00 đến 22:00 .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL Server 2016:Trình thiết kế truy vấn

  2. sp_add_schedule so với sp_add_jobschedule trong SQL Server:Sự khác biệt là gì?

  3. Cách ORIGINAL_DB_NAME () hoạt động trong SQL Server

  4. Mỗi biểu thức GROUP BY phải chứa ít nhất một cột không phải là tham chiếu bên ngoài

  5. Chức năng Lead () và LAG () trong SQL Server 2008