75

SQL Server で、DATETIME を秒/分/時間/日/年に "フロアリング" するにはどうすればよいですか?

日付が2008-09-17 12:56:53.430であるとすると、フローリングの出力は次のようになります。

  • 年: 2008-01-01 00:00:00.000
  • 月: 2008-09-01 00:00:00.000
  • 日: 2008-09-17 00:00:00.000
  • 時間: 2008-09-17 12:00:00.000
  • 分: 2008-09-17 12:56:00.000
  • 2 番目: 2008-09-17 12:56:53.000
4

9 に答える 9

109

重要なのは、DATEADDDATEDIFFを適切な SQL タイムスパン列挙と共に使用することです。

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

秒単位でフローリングを行っている場合、0 を使用すると算術オーバーフローが発生することが多いことに注意してください。

于 2008-09-17T17:01:36.500 に答える
30

SQL Server では、これを行うためのちょっとしたコツがあります。

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

DateTime を float にキャストします。これは、Date を整数部分として表し、Time を 1 日の分数として表します。その小数部分を切り取り、それを DateTime にキャストすると、その日の最初の真夜中になります。

これはおそらく、すべての DATEADD および DATEDIFF のものよりも効率的です。確かに入力しやすいです。

于 2008-09-17T19:08:32.403 に答える
12

Convert/Cast ソリューションを拡張すると、Microsoft SQL Server 2008 では次のことが可能になります。

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

getdate()日時である任意の列に置き換えるだけです。

この変換に含まれる文字列はありません。

これは、アドホック クエリまたは更新では問題ありませんが、キー結合または頻繁に使用される処理では、処理内で変換を処理するか、適切なキーとデータを持つようにテーブルを再定義する方がよい場合があります。

2005 年には、メッシアー フロアを使用できます。cast(floor(cast(getdate() as float)) as datetime)

文字列変換も使用していないと思いますが、実際の効率と安楽椅子の見積もりを比較することはできません。

于 2012-04-18T15:20:00.317 に答える
6

私は@Portmanの答えを何年にもわたって参照として使用してきました。

私はその性能を主張するものではなく、単にユーザーのためのツールとして提供するだけです.

私のコードは彼の派生物であるため、この回答に賛成票を投じる場合は、 @Portman の回答にも賛成票を投じてください。

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

使用法:

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
于 2013-07-25T14:22:45.573 に答える
2

使用するスタイルによっては、CONVERT()関数でもこれを行うことができます。

于 2008-09-17T17:04:00.003 に答える
1

残念ながら Oracle ではありません。それ以外の場合は、trunc() または to_char() を使用できます。

しかし、SQL Server にも同様の問題があり、ここで参照されているように、CONVERT() および DateDiff() メソッドを使用しました。

于 2008-09-17T17:27:37.530 に答える
0

この猫の皮を剥ぐ方法はいくつかあります =)

select convert(datetime,convert(varchar,CURRENT_TIMESTAMP,101))
于 2014-10-02T17:27:12.570 に答える
-1

PostgreSQLも「SQL Server」なので、言及します

date_trunc()

これは、まさにあなたが求めていることを優雅に行います。

例えば:

select date_trunc('hour',current_timestamp);
       date_trunc
------------------------
 2009-02-18 07:00:00-08
(1行)

于 2009-02-18T15:46:30.357 に答える