DATE_BUCKET (Transact-SQL)

適用於:SQL Server 2022 (16.x) Azure SQL DatabaseAzure SQL Managed InstanceAzure SQL Edge

此函式會從 origin 參數所定義的時間戳記 (如果未指定 origin 參數,則會從 1900-01-01 00:00:00.000 的預設原始值),傳回對應至每個日期時間值區起點的日期時間值。

如需所有 Transact-SQL 日期和時間資料類型與函式的概觀,請參閱日期和時間資料類型與函式 (Transact-SQL)

Transact-SQL 語法慣例

語法

DATE_BUCKET (datepart, number, date [, origin ] )

引數

datepart

number 參數搭配使用的 date 部分,例如 year、month、day、minute、second。

DATE_BUCKET 不會接受 datepart 引數的使用者定義變數對等項目。

datepart 縮寫
day dd, d
week wk, ww
month mm, m
quarter qq, q
year yy, yyyy
hour hh
minute mi, n
second ss, s
millisecond ms

number

決定值區寬度並與 datePart 引數結合的整數。 這代表從原始時間起算的 datepart 值區寬度。 這個引數不能是負整數值。

date

可解析成下列其中一個值的運算式:

  • date
  • datetime
  • datetime2
  • datetimeoffset
  • smalldatetime
  • time

針對 dateDATE_BUCKET 會接受資料行運算式、運算式或使用者定義的變數,前提是其必須解析為上述任何資料類型。

origin

可解析成下列其中一個值的選擇性運算式:

  • date
  • datetime
  • datetime2
  • datetimeoffset
  • smalldatetime
  • time

origin 的資料類型應符合 date 參數的資料類型。

如果未針對函式指定任何 origin 值,則 DATE_BUCKET 會使用 1900-01-01 00:00:00.000 的預設原始日期值,也就是 1900 年 1 月 1 日星期一上午 12:00。

傳回類型

這個方法的傳回值資料類型為動態。 傳回型別取決於提供給 date 的引數而定。 如果提供有效的輸入資料類型給 dateDATE_BUCKET 便會傳回相同的資料類型。 如果為 date 參數指定了字串常值,DATE_BUCKET 就會引發錯誤。

傳回值

了解 DATE_BUCKET 的輸出

DATE_BUCKET 會傳回與 datepartnumber 參數對應的最新日期或時間值。 例如在下列運算式中,DATE_BUCKET 會傳回 2020-04-13 00:00:00.0000000 的輸出值,因為輸出的計算依據是從預設原始時間 1900-01-01 00:00:00.000 起算為期一週的值區。 值 2020-04-13 00:00:00.0000000 是在原始值 1900-01-01 00:00:00.000 後的 6,276 週。

DECLARE @date DATETIME2 = '2020-04-15 21:22:11';
SELECT DATE_BUCKET(WEEK, 1, @date);

針對下列所有運算式,系統將會傳回相同的輸出值 2020-04-13 00:00:00.0000000。 這是因為 2020-04-13 00:00:00.0000000 是在原始日期後的 6,276 週,而 6,276 可由 2、3、4 和 6 整除。

DECLARE @date DATETIME2 = '2020-04-15 21:22:11';
SELECT DATE_BUCKET(WEEK, 2, @date);
SELECT DATE_BUCKET(WEEK, 3, @date);
SELECT DATE_BUCKET(WEEK, 4, @date);
SELECT DATE_BUCKET(WEEK, 6, @date);

下列運算式的輸出是 2020-04-06 00:00:00.0000000,這是預設原始時間 1900-01-01 00:00:00.000 後的 6275 週。

DECLARE @date DATETIME2 = '2020-04-15 21:22:11';
SELECT DATE_BUCKET(WEEK, 5, @date);

下列運算式的輸出是 2020-06-09 00:00:00.0000000,這是指定原始時間 2019-01-01 00:00:00 後的 75 週。

DECLARE @date DATETIME2 = '2020-06-15 21:22:11';
DECLARE @origin DATETIME2 = '2019-01-01 00:00:00';
SELECT DATE_BUCKET(WEEK, 5, @date, @origin);

datepart 引數

dayofyeardayweekday 都會傳回相同的值。 每個 datepart 及其縮寫都會傳回相同的值。

number 引數

number 引數不得超過正數 int 值的範圍。 在下列陳述式中,number 引數超過 int 的範圍 (超過 1)。 下列陳述式會傳回錯誤訊息 Msg 8115, Level 16, State 2, Line 2. Arithmetic overflow error converting expression to data type int.

DECLARE @date DATETIME2 = '2020-04-30 00:00:00';
SELECT DATE_BUCKET(DAY, 2147483648, @date);

如果將負數的 number 值傳遞給 DATE_BUCKET 函式,則會傳回下列錯誤。

Msg 9834, Level 16, State 1, Line 1
Invalid bucket width value passed to DATE_BUCKET function. Only positive values are allowed.

date 引數

DATE_BUCKET 會傳回與 date 引數的資料類型對應的基底值。 在下列範例中,系統會傳回具有 datetime2 資料類型的輸出值。

SELECT DATE_BUCKET(DAY, 10, SYSUTCDATETIME());

origin 引數

origindate 引數的資料類型必須相同。 如果使用不同的資料類型,將會產生錯誤。

備註

在下列子句中使用 DATE_BUCKET

  • GROUP BY
  • HAVING
  • 排序依據
  • SELECT <list>
  • WHERE

範例

A. 使用值區寬度 1 從原始時間計算 DATE_BUCKET

這些陳述式各自會從原始時間以值區寬度 1 遞增 DATE_BUCKET

DECLARE @date DATETIME2 = '2020-04-30 21:21:21';
SELECT 'Week', DATE_BUCKET(WEEK, 1, @date)
UNION ALL
SELECT 'Day', DATE_BUCKET(DAY, 1, @date)
UNION ALL
SELECT 'Hour', DATE_BUCKET(HOUR, 1, @date)
UNION ALL
SELECT 'Minutes', DATE_BUCKET(MINUTE, 1, @date)
UNION ALL
SELECT 'Seconds', DATE_BUCKET(SECOND, 1, @date);

結果集如下所示。

Week    2020-04-27 00:00:00.0000000
Day     2020-04-30 00:00:00.0000000
Hour    2020-04-30 21:00:00.0000000
Minutes 2020-04-30 21:21:00.0000000
Seconds 2020-04-30 21:21:21.0000000

B. 使用運算式當做 number 和 date 參數的引數

這些範例會使用不同的運算式類型,作為 numberdate 參數的引數。

這些範例是使用 AdventureWorksDW2022 資料庫所建置的。

將使用者自訂變數指定為 number 和 date

此範例會將使用者定義變數指定為 numberdate 的引數:

DECLARE @days INT = 365,
    @datetime DATETIME2 = '2000-01-01 01:01:01.1110000';
    /* 2000 was a leap year */;
SELECT DATE_BUCKET(DAY, @days, @datetime);

結果集如下所示。

1999-12-08 00:00:00.0000000

將資料行指定為 date

在下列範例中,我們會計算依每週日期值區分組的 OrderQuantity 總和以及 UnitPrice 總和。

SELECT DATE_BUCKET(WEEK, 1, CAST(ShipDate AS DATETIME2)) AS ShippedDateBucket
    , SUM(OrderQuantity) AS SumOrderQuantity
    , SUM(UnitPrice) AS SumUnitPrice
FROM dbo.FactInternetSales FIS
WHERE ShipDate BETWEEN '2011-01-03 00:00:00.000'
        AND '2011-02-28 00:00:00.000'
GROUP BY DATE_BUCKET(WEEK, 1, CAST(ShipDate AS DATETIME2))
ORDER BY ShippedDateBucket;

結果集如下所示。

ShippedDateBucket           SumOrderQuantity SumUnitPrice
--------------------------- ---------------- ---------------------
2011-01-03 00:00:00.0000000 21               65589.7546
2011-01-10 00:00:00.0000000 27               89938.5464
2011-01-17 00:00:00.0000000 31               104404.9064
2011-01-24 00:00:00.0000000 36               118525.6846
2011-01-31 00:00:00.0000000 39               123555.431
2011-02-07 00:00:00.0000000 35               109342.351
2011-02-14 00:00:00.0000000 32               107804.8964
2011-02-21 00:00:00.0000000 37               119456.3428
2011-02-28 00:00:00.0000000 9                28968.6982

將純量系統函數指定為 date

這個範例會針對 date 指定 SYSDATETIME。 傳回的精確值取決於陳述式執行的日期和時間:

SELECT DATE_BUCKET(WEEK, 10, SYSDATETIME());

結果集如下所示。

2020-03-02 00:00:00.0000000

將純量子查詢和純量函數指定為 number 和 date

此範例會使用純量子查詢 MAX(OrderDate),作為 numberdate 的引數。 (SELECT top 1 CustomerKey FROM dbo.DimCustomer where GeographyKey > 100) 會作為 number 參數的人工引數,以示範如何從值清單中選取 number 引數。

SELECT DATE_BUCKET(WEEK, (
    SELECT TOP 1 CustomerKey
    FROM dbo.DimCustomer
    WHERE GeographyKey > 100
    ), (
    SELECT MAX(OrderDate)
    FROM dbo.FactInternetSales
));

將數值運算式和純量系統函數指定為 number 和 date

此範例會使用數值運算式 ((10/2)) 和純量系統函數 (SYSDATETIME) 作為 number 和 date 的引數。

SELECT DATE_BUCKET(WEEK, (10/2), SYSDATETIME());

將彙總視窗函式指定為 number

此範例會使用彙總視窗函式,作為 number 的引數。

SELECT DISTINCT DATE_BUCKET(DAY, 30, CAST([ShipDate] AS DATETIME2)) AS DateBucket
    , FIRST_VALUE([SalesOrderNumber]) OVER (
        ORDER BY DATE_BUCKET(DAY, 30, CAST([ShipDate] AS DATETIME2))
        ) AS First_Value_In_Bucket
    , LAST_VALUE([SalesOrderNumber]) OVER (
        ORDER BY DATE_BUCKET(DAY, 30, CAST([ShipDate] AS DATETIME2))
        ) AS Last_Value_In_Bucket
FROM [dbo].[FactInternetSales]
WHERE ShipDate BETWEEN '2011-01-03 00:00:00.000'
        AND '2011-02-28 00:00:00.000'
ORDER BY DateBucket;
GO

C. 使用非預設原始值

此範例會使用非預設原始值來產生日期值區。

DECLARE @date DATETIME2 = '2020-06-15 21:22:11';
DECLARE @origin DATETIME2 = '2019-01-01 00:00:00';
SELECT DATE_BUCKET(HOUR, 2, @date, @origin);

另請參閱