it-swarm-vi.tech

Sàn một ngày trong máy chủ SQL

Trong SQL Server, làm cách nào để tôi "chuyển" một cơ sở dữ liệu sang giây/phút/giờ/ngày/năm?

Giả sử tôi có ngày 2008-09-17 12: 56: 53.430 , thì đầu ra của sàn nên là:

  • Năm: 2008-01-01 00: 00: 00.000
  • Tháng: 2008-09-01 00: 00: 00.000
  • Ngày: 2008-09-17 00: 00: 00.000
  • Giờ: 2008-09-17 12: 00: 00.000
  • Phút: 2008-09-17 12: 56: 00.000
  • Thứ hai: 2008-09-17 12: 56: 53.000
65
Portman

Chìa khóa là sử dụng DATEADDDATEIFF cùng với phép liệt kê thời gian SQL thích hợp.

declare @datetime datetime;
set @datetime = getdate();
select @datetime;
select dateadd(year,datediff(year,0,@datetime),0);
select dateadd(month,datediff(month,0,@datetime),0);
select dateadd(day,datediff(day,0,@datetime),0);
select dateadd(hour,datediff(hour,0,@datetime),0);
select dateadd(minute,datediff(minute,0,@datetime),0);
select dateadd(second,datediff(second,'2000-01-01',@datetime),'2000-01-01');
select dateadd(week,datediff(week,0,@datetime),-1); --Beginning of week is Sunday
select dateadd(week,datediff(week,0,@datetime),0); --Beginning of week is Monday

Lưu ý rằng khi bạn xếp sàn lần thứ hai, bạn sẽ thường xuyên bị tràn số học nếu bạn sử dụng 0. Vì vậy, hãy chọn một giá trị đã biết được đảm bảo thấp hơn thời gian bạn đang cố gắng lên sàn.

94
Portman

Trong SQL Server, đây là một mẹo nhỏ để làm điều đó:

SELECT CAST(FLOOR(CAST(CURRENT_TIMESTAMP AS float)) AS DATETIME)

Bạn đặt DateTime thành một số float, đại diện cho Ngày là phần nguyên và Thời gian là phần của một ngày trôi qua. Cắt bỏ phần thập phân đó, sau đó chuyển nó trở lại DateTime và bạn đã có nửa đêm vào đầu ngày hôm đó.

Điều này có lẽ hiệu quả hơn tất cả các công cụ DATEADD và DATEDIFF. Đó chắc chắn là cách dễ dàng hơn để gõ.

28
Chris Wuestefeld

Mở rộng dựa trên giải pháp Chuyển đổi/Truyền, trong Microsoft SQL Server 2008, bạn có thể thực hiện các thao tác sau:

cast(cast(getdate() as date) as datetime)

Chỉ cần thay thế getdate() bằng bất kỳ cột nào là datetime.

Không có chuỗi liên quan đến việc chuyển đổi này.

Điều này ổn đối với các truy vấn hoặc cập nhật đặc biệt, nhưng đối với các phép nối chính hoặc xử lý được sử dụng nhiều, có thể tốt hơn để xử lý chuyển đổi trong quá trình xử lý hoặc xác định lại các bảng để có khóa và dữ liệu phù hợp.

Vào năm 2005, bạn có thể sử dụng sàn lộn xộn hơn: cast(floor(cast(getdate() as float)) as datetime)

Tôi không nghĩ rằng sử dụng chuyển đổi chuỗi, nhưng tôi không thể nói để so sánh hiệu quả thực tế so với ước tính ghế bành.

11
Moe Cazzell

Tôi đã sử dụng câu trả lời của @ Portman nhiều lần trong nhiều năm làm tài liệu tham khảo khi sàn ngày và đã chuyển nó hoạt động thành một chức năng mà bạn có thể thấy hữu ích.

Tôi không khẳng định về hiệu suất của nó và chỉ cung cấp nó như một công cụ cho người dùng.

Tôi yêu cầu rằng, nếu bạn quyết định nâng cấp câu trả lời này, vui lòng upvote @ Portman's answer , vì mã của tôi là một dẫn xuất của anh ấy.

IF OBJECT_ID('fn_FloorDate') IS NOT NULL DROP FUNCTION fn_FloorDate
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[fn_FloorDate] (
  @Date DATETIME = NULL,
  @DatePart VARCHAR(6) = 'day'
)
RETURNS DATETIME
AS
BEGIN
  IF (@Date IS NULL)
    SET @Date = GETDATE();

  RETURN
  CASE
    WHEN LOWER(@DatePart) = 'year' THEN DATEADD(YEAR, DATEDIFF(YEAR, 0, @Date), 0)
    WHEN LOWER(@DatePart) = 'month' THEN DATEADD(MONTH, DATEDIFF(MONTH, 0, @Date), 0)
    WHEN LOWER(@DatePart) = 'day' THEN DATEADD(DAY, DATEDIFF(DAY, 0, @Date), 0)
    WHEN LOWER(@DatePart) = 'hour' THEN DATEADD(HOUR, DATEDIFF(HOUR, 0, @Date), 0)
    WHEN LOWER(@DatePart) = 'minute' THEN DATEADD(MINUTE, DATEDIFF(MINUTE, 0, @Date), 0)
    WHEN LOWER(@DatePart) = 'second' THEN DATEADD(SECOND, DATEDIFF(SECOND, '2000-01-01', @Date), '2000-01-01')
    ELSE DATEADD(DAY, DATEDIFF(DAY, 0, @Date), 0)
  END;
END

Sử dụng:

DECLARE @date DATETIME;
SET @date = '2008-09-17 12:56:53.430';

SELECT
  @date AS [Now],--2008-09-17 12:56:53.430
  dbo.fn_FloorDate(@date, 'year') AS [Year],--2008-01-01 00:00:00.000
  dbo.fn_FloorDate(default, default) AS [NoParams],--2013-11-05 00:00:00.000
  dbo.fn_FloorDate(@date, default) AS [ShouldBeDay],--2008-09-17 00:00:00.000
  dbo.fn_FloorDate(@date, 'month') AS [Month],--2008-09-01 00:00:00.000
  dbo.fn_FloorDate(@date, 'day') AS [Day],--2008-09-17 00:00:00.000
  dbo.fn_FloorDate(@date, 'hour') AS [Hour],--2008-09-17 12:00:00.000
  dbo.fn_FloorDate(@date, 'minute') AS [Minute],--2008-09-17 12:56:00.000
  dbo.fn_FloorDate(@date, 'second') AS [Second];--2008-09-17 12:56:53.000
6
Dan Atkinson

Hàm CONVERT () cũng có thể làm điều này, tùy thuộc vào kiểu bạn sử dụng.

2
Joel Coehoorn

Quá tệ, đó không phải là Oracle, hoặc người nào khác bạn có thể sử dụng trunc () hoặc to_char ().

Nhưng tôi gặp vấn đề tương tự với SQL Server và đã sử dụng các phương thức CONVERT () và DateDiff (), như được tham chiếu tại đây

1
typicalrunt

Có một số cách để da con mèo này =)

select convert(datetime,convert(varchar,CURRENT_TIMESTAMP,101))
0
Sean

DateAdd cùng với DateDiff có thể giúp thực hiện nhiều nhiệm vụ khác nhau. Ví dụ: bạn có thể tìm thấy ngày cuối cùng của bất kỳ tháng nào và cũng có thể tìm thấy ngày cuối cùng của tháng trước hoặc tháng tiếp theo. 

----Last Day of Previous Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0))
LastDay_PreviousMonth
----Last Day of Current Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+1,0))
LastDay_CurrentMonth
----Last Day of Next Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+2,0))
LastDay_NextMonth

Nguồn

0
pinaldave