Skip to content

Commit ea45e86

Browse files
authored
Refresh DATE_BUCKET article (#35721)
1 parent 9c94163 commit ea45e86

2 files changed

Lines changed: 99 additions & 95 deletions

File tree

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
---
22
author: MashaMSFT
33
ms.author: mathoma
4-
ms.date: 11/29/2022
4+
ms.date: 11/03/2025
55
ms.service: sql
66
ms.topic: include
77
---
88

9-
[!INCLUDE [Applies to](../applies-md.md)] [!INCLUDE [SQL Server 2022](_ss2022.md)] [!INCLUDE [Azure SQL Database](_asdb.md)] [!INCLUDE [Azure SQL Managed Instance](_asmi.md)] [!INCLUDE [Azure SQL Edge](_asde.md)]
9+
[!INCLUDE [Applies to](../applies-md.md)] [!INCLUDE [SQL Server 2022](_ss2022.md)] and later versions [!INCLUDE [Azure SQL Database](_asdb.md)] [!INCLUDE [Azure SQL Managed Instance](_asmi.md)] [!INCLUDE [Azure SQL Edge](_asde.md)]
Lines changed: 97 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
---
22
title: "DATE_BUCKET (Transact-SQL)"
3-
description: "DATE_BUCKET (Transact-SQL)"
3+
description: DATE_BUCKET returns the date-time value corresponding to the start of each date-time bucket from a defined origin timestamp.
44
author: kendalvandyke
55
ms.author: kendalv
66
ms.reviewer: randolphwest
7-
ms.date: 05/09/2022
7+
ms.date: 11/03/2025
88
ms.service: sql
99
ms.subservice: t-sql
1010
ms.topic: reference
@@ -15,51 +15,51 @@ helpviewer_keywords:
1515
- "DATE_BUCKET function"
1616
- "analytic functions, DATE_BUCKET"
1717
dev_langs:
18-
- "TSQL"
18+
- TSQL
1919
---
2020
# DATE_BUCKET (Transact-SQL)
2121

2222
[!INCLUDE [sqlserver2022-asde](../../includes/applies-to-version/sqlserver2022-asdb-asmi-asde.md)]
2323

24-
This function returns the date-time value corresponding to the start of each date-time bucket from the timestamp defined by the `origin` parameter, or the default origin value of `1900-01-01 00:00:00.000` if the origin parameter isn't specified.
24+
This function returns the date-time value corresponding to the start of each date-time bucket from the timestamp defined by the *origin* parameter, or the default origin value of `1900-01-01 00:00:00.000` if the origin parameter isn't specified.
2525

26-
See [Date and Time Data Types and Functions (Transact-SQL)](../functions/date-and-time-data-types-and-functions-transact-sql.md) for an overview of all Transact-SQL date and time data types and functions.
26+
See [Date and time data types and functions](date-and-time-data-types-and-functions-transact-sql.md) for an overview of all Transact-SQL date and time data types and functions.
2727

2828
:::image type="icon" source="../../includes/media/topic-link-icon.svg" border="false"::: [Transact-SQL syntax conventions](../language-elements/transact-sql-syntax-conventions-transact-sql.md)
2929

3030
## Syntax
3131

3232
```syntaxsql
33-
DATE_BUCKET (datepart, number, date [, origin ] )
33+
DATE_BUCKET (datepart , number , date [ , origin ] )
3434
```
3535

3636
## Arguments
3737

3838
#### *datepart*
3939

40-
The part of *date* that is used with the `number` parameter, for example, year, month, day, minute, second.
40+
The part of *date* that is used with the *number* parameter, for example, **year**, **month**, **day**, **minute**, **second**.
4141

4242
`DATE_BUCKET` doesn't accept user-defined variable equivalents for the *datepart* arguments.
4343

44-
|*datepart*|Abbreviations|
45-
|---|---|
46-
|**day**|**dd**, **d**|
47-
|**week**|**wk**, **ww**|
48-
|**month**|**mm**, **m**|
49-
|**quarter**|**qq**, **q**|
50-
|**year**|**yy**, **yyyy**|
51-
|**hour**|**hh**|
52-
|**minute**|**mi**, **n**|
53-
|**second**|**ss**, **s**|
54-
|**millisecond**|**ms**|
44+
| *datepart* | Abbreviations |
45+
| --- | --- |
46+
| **day** | **dd**, **d** |
47+
| **week** | **wk**, **ww** |
48+
| **month** | **mm**, **m** |
49+
| **quarter** | **qq**, **q** |
50+
| **year** | **yy**, **yyyy** |
51+
| **hour** | **hh** |
52+
| **minute** | **mi**, **n** |
53+
| **second** | **ss**, **s** |
54+
| **millisecond** | **ms** |
5555

5656
#### *number*
5757

58-
The integer number that decides the width of the bucket combined with *datepart* argument. This represents the width of the *datepart* buckets from the origin time. This argument can't be a negative integer value.
58+
The integer number that decides the width of the bucket combined with *datepart* argument. This argument represents the width of the *datepart* buckets from the origin time. This argument can't be a negative integer value.
5959

6060
#### *date*
6161

62-
An expression that can resolve to one of the following values:
62+
An expression that must be one of the following values:
6363

6464
- **date**
6565
- **datetime**
@@ -68,7 +68,7 @@ An expression that can resolve to one of the following values:
6868
- **smalldatetime**
6969
- **time**
7070

71-
For **date**, `DATE_BUCKET` will accept a column expression, expression, or user-defined variable if they resolve to any of the data types mentioned above.
71+
For **date**, `DATE_BUCKET` accepts a column expression, expression, or user-defined variable if they resolve to any of the data types mentioned previously.
7272

7373
#### *origin*
7474

@@ -81,112 +81,116 @@ An optional expression that can resolve to one of the following values:
8181
- **smalldatetime**
8282
- **time**
8383

84-
The data type for `origin` should match the data type of the `date` parameter.
84+
The data type for *origin* should match the data type of the *date* parameter.
8585

86-
`DATE_BUCKET` uses a default origin date value of `1900-01-01 00:00:00.000` that is, 12:00 AM on Monday, January 1, 1900, if no `origin` value is specified for the function.
86+
`DATE_BUCKET` uses a default origin date value of `1900-01-01 00:00:00.000` that is, 12:00 AM on Monday, January 1, 1900, if no *origin* value is specified for the function.
8787

88-
## Return type
88+
## Return types
8989

90-
The return value data type for this method is dynamic. The return type depends on the argument supplied for `date`. If a valid input data type is supplied for `date`, `DATE_BUCKET` returns the same data type. `DATE_BUCKET` raises an error if a string literal is specified for the `date` parameter.
90+
The return value data type for this method is dynamic. The return type depends on the argument supplied for *date*. If a valid input data type is supplied for *date*, `DATE_BUCKET` returns the same data type. `DATE_BUCKET` raises an error if a string literal is specified for the *date* parameter.
9191

92-
## Return values
92+
## Return value
9393

94-
### Understanding the output from `DATE_BUCKET`
94+
### Understand the output from DATE_BUCKET
9595

96-
`DATE_BUCKET` returns the latest date or time value, corresponding to the *datepart* and *number* parameter. For example, in the expressions below, `DATE_BUCKET` will return the output value of `2020-04-13 00:00:00.0000000`, as the output is calculated based on one week buckets from the default origin time of `1900-01-01 00:00:00.000`. The value `2020-04-13 00:00:00.0000000` is 6,276 weeks from the origin value of `1900-01-01 00:00:00.000`.
96+
`DATE_BUCKET` returns the latest date or time value, corresponding to the *datepart* and *number* parameter. For example, in the following expressions, `DATE_BUCKET` returns the output value of `2020-04-13 00:00:00.0000000`, as the output is calculated based on one week buckets from the default origin time of `1900-01-01 00:00:00.000`. The value `2020-04-13 00:00:00.0000000` is 6,276 weeks from the origin value of `1900-01-01 00:00:00.000`.
9797

9898
```sql
99-
DECLARE @date DATETIME2 = '2020-04-15 21:22:11';
99+
DECLARE @date AS DATETIME2 = '2020-04-15 21:22:11';
100+
100101
SELECT DATE_BUCKET(WEEK, 1, @date);
101102
```
102103

103-
For all the expressions below, the same output value of `2020-04-13 00:00:00.0000000` will be returned. This is because `2020-04-13 00:00:00.0000000` is 6,276 weeks from the origin date, and 6,276 is divisible by 2, 3, 4 and 6.
104+
For all the following expressions, the same output value of `2020-04-13 00:00:00.0000000` is returned. This is because `2020-04-13 00:00:00.0000000` is 6,276 weeks from the origin date, and 6,276 is divisible by 2, 3, 4 and 6.
104105

105106
```sql
106-
DECLARE @date DATETIME2 = '2020-04-15 21:22:11';
107+
DECLARE @date AS DATETIME2 = '2020-04-15 21:22:11';
108+
107109
SELECT DATE_BUCKET(WEEK, 2, @date);
108110
SELECT DATE_BUCKET(WEEK, 3, @date);
109111
SELECT DATE_BUCKET(WEEK, 4, @date);
110112
SELECT DATE_BUCKET(WEEK, 6, @date);
111113
```
112114

113-
The output for the expression below is `2020-04-06 00:00:00.0000000`, which is 6275 weeks from the default origin time `1900-01-01 00:00:00.000`.
115+
The output for the following expression is `2020-04-06 00:00:00.0000000`, which is 6,275 weeks from the default origin time `1900-01-01 00:00:00.000`.
114116

115117
```sql
116-
DECLARE @date DATETIME2 = '2020-04-15 21:22:11';
118+
DECLARE @date AS DATETIME2 = '2020-04-15 21:22:11';
119+
117120
SELECT DATE_BUCKET(WEEK, 5, @date);
118121
```
119122

120-
The output for the expression below is `2020-06-09 00:00:00.0000000`, which is 75 weeks from the specified origin time `2019-01-01 00:00:00`.
123+
The output for the following expression is `2020-06-09 00:00:00.0000000`, which is 75 weeks from the specified origin time `2019-01-01 00:00:00`.
121124

122125
```sql
123-
DECLARE @date DATETIME2 = '2020-06-15 21:22:11';
124-
DECLARE @origin DATETIME2 = '2019-01-01 00:00:00';
126+
DECLARE @date AS DATETIME2 = '2020-06-15 21:22:11';
127+
DECLARE @origin AS DATETIME2 = '2019-01-01 00:00:00';
128+
125129
SELECT DATE_BUCKET(WEEK, 5, @date, @origin);
126130
```
127131

128-
## datepart argument
132+
## The *datepart* argument
129133

130134
**dayofyear**, **day**, and **weekday** return the same value. Each *datepart* and its abbreviations return the same value.
131135

132-
## number argument
136+
## The *number* argument
133137

134-
The *number* argument can't exceed the range of positive **int** values. In the following statements, the argument for *number* exceeds the range of **int** by 1. The following statement returns the error message, `Msg 8115, Level 16, State 2, Line 2. Arithmetic overflow error converting expression to data type int.`
138+
The *number* argument can't exceed the range of positive **int** values. In the following statements, the argument for *number* exceeds the range of **int** by 1. The following statement returns the error message: `Msg 8115, Level 16, State 2, Line 2. Arithmetic overflow error converting expression to data type int.`
135139

136140
```sql
137-
DECLARE @date DATETIME2 = '2020-04-30 00:00:00';
141+
DECLARE @date AS DATETIME2 = '2020-04-30 00:00:00';
142+
138143
SELECT DATE_BUCKET(DAY, 2147483648, @date);
139144
```
140145

141-
If a negative value for number is passed to the `DATE_BUCKET` function, the following error will be returned.
146+
If a negative value for number is passed to the `DATE_BUCKET` function, the following error is returned.
142147

143148
```text
144149
Msg 9834, Level 16, State 1, Line 1
145150
Invalid bucket width value passed to DATE_BUCKET function. Only positive values are allowed.
146151
```
147152

148-
## date argument
153+
## The *date* argument
149154

150-
`DATE_BUCKET` return the base value corresponding to the data type of the `date` argument. In the following example, an output value with datetime2 datatype is returned.
155+
`DATE_BUCKET` return the base value corresponding to the data type of the *date* argument. In the following example, an output value with datetime2 data type is returned.
151156

152157
```sql
153158
SELECT DATE_BUCKET(DAY, 10, SYSUTCDATETIME());
154159
```
155160

156-
## origin argument
161+
## The *origin* argument
157162

158-
The data type of the `origin` and `date` arguments in must be the same. If different data types are used, an error will be generated.
163+
The data type of the *origin* and *date* arguments in must be the same. If different data types are used, an error is generated.
159164

160165
## Remarks
161166

162167
Use `DATE_BUCKET` in the following clauses:
163168

164-
- GROUP BY
165-
- HAVING
166-
- ORDER BY
167-
- SELECT \<list>
168-
- WHERE
169+
- `GROUP BY`
170+
- `HAVING`
171+
- `ORDER BY`
172+
- `SELECT <list>`
173+
- `WHERE`
169174

170175
## Examples
171176

177+
[!INCLUDE [article-uses-adventureworks](../../includes/article-uses-adventureworks.md)]
178+
172179
### A. Calculate DATE_BUCKET with a bucket width of 1 from the origin time
173180

174181
Each of these statements increments `DATE_BUCKET` with a bucket width of 1 from the origin time:
175182

176183
```sql
177-
DECLARE @date DATETIME2 = '2020-04-30 21:21:21';
184+
DECLARE @date AS DATETIME2 = '2020-04-30 21:21:21';
185+
178186
SELECT 'Week', DATE_BUCKET(WEEK, 1, @date)
179-
UNION ALL
180-
SELECT 'Day', DATE_BUCKET(DAY, 1, @date)
181-
UNION ALL
182-
SELECT 'Hour', DATE_BUCKET(HOUR, 1, @date)
183-
UNION ALL
184-
SELECT 'Minutes', DATE_BUCKET(MINUTE, 1, @date)
185-
UNION ALL
186-
SELECT 'Seconds', DATE_BUCKET(SECOND, 1, @date);
187+
UNION ALL SELECT 'Day', DATE_BUCKET(DAY, 1, @date)
188+
UNION ALL SELECT 'Hour', DATE_BUCKET(HOUR, 1, @date)
189+
UNION ALL SELECT 'Minutes', DATE_BUCKET(MINUTE, 1, @date)
190+
UNION ALL SELECT 'Seconds', DATE_BUCKET(SECOND, 1, @date);
187191
```
188192

189-
Here's the result set.
193+
[!INCLUDE [ssresult-md](../../includes/ssresult-md.md)]
190194

191195
```output
192196
Week 2020-04-27 00:00:00.0000000
@@ -207,34 +211,33 @@ These examples are built using the [!INCLUDE [sssampledbdwobject-md](../../inclu
207211
This example specifies user-defined variables as arguments for *number* and *date*:
208212

209213
```sql
210-
DECLARE @days INT = 365,
211-
@datetime DATETIME2 = '2000-01-01 01:01:01.1110000';
212-
/* 2000 was a leap year */;
214+
DECLARE @days AS INT = 365,
215+
@datetime AS DATETIME2 = '2000-01-01 01:01:01.1110000';
216+
213217
SELECT DATE_BUCKET(DAY, @days, @datetime);
214218
```
215219

216-
Here's the result set.
220+
[!INCLUDE [ssresult-md](../../includes/ssresult-md.md)]
217221

218222
```output
219223
1999-12-08 00:00:00.0000000
220224
```
221225

222226
#### Specify a column as date
223227

224-
In the example below, we're calculating the sum of `OrderQuantity` and sum of `UnitPrice` grouped over weekly date buckets.
228+
In the following example, we calculate the sum of `OrderQuantity` and sum of `UnitPrice` grouped over weekly date buckets.
225229

226230
```sql
227-
SELECT DATE_BUCKET(WEEK, 1, CAST(ShipDate AS DATETIME2)) AS ShippedDateBucket
228-
, SUM(OrderQuantity) AS SumOrderQuantity
229-
, SUM(UnitPrice) AS SumUnitPrice
230-
FROM dbo.FactInternetSales FIS
231-
WHERE ShipDate BETWEEN '2011-01-03 00:00:00.000'
232-
AND '2011-02-28 00:00:00.000'
233-
GROUP BY DATE_BUCKET(WEEK, 1, CAST(ShipDate AS DATETIME2))
231+
SELECT DATE_BUCKET(WEEK, 1, CAST (ShipDate AS DATETIME2)) AS ShippedDateBucket,
232+
SUM(OrderQuantity) AS SumOrderQuantity,
233+
SUM(UnitPrice) AS SumUnitPrice
234+
FROM dbo.FactInternetSales AS FIS
235+
WHERE ShipDate BETWEEN '2011-01-03 00:00:00.000' AND '2011-02-28 00:00:00.000'
236+
GROUP BY DATE_BUCKET(WEEK, 1, CAST (ShipDate AS DATETIME2))
234237
ORDER BY ShippedDateBucket;
235238
```
236239

237-
Here's the result set.
240+
[!INCLUDE [ssresult-md](../../includes/ssresult-md.md)]
238241

239242
```output
240243
ShippedDateBucket SumOrderQuantity SumUnitPrice
@@ -258,50 +261,50 @@ This example specifies `SYSDATETIME` for *date*. The exact value returned depend
258261
SELECT DATE_BUCKET(WEEK, 10, SYSDATETIME());
259262
```
260263

261-
Here's the result set.
264+
[!INCLUDE [ssresult-md](../../includes/ssresult-md.md)]
262265

263266
```output
264267
2020-03-02 00:00:00.0000000
265268
```
266269

267270
#### Specify scalar subqueries and scalar functions as number and date
268271

269-
This example uses scalar subqueries, `MAX(OrderDate)`, as arguments for *number* and *date*. `(SELECT top 1 CustomerKey FROM dbo.DimCustomer where GeographyKey > 100)` serves as an artificial argument for the number parameter, to show how to select a *number* argument from a value list.
272+
This example uses scalar subqueries, `MAX(OrderDate)`, as arguments for *number* and *date*. `(SELECT TOP 1 CustomerKey FROM dbo.DimCustomer WHERE GeographyKey > 100)` serves as an artificial argument for the number parameter, to show how to select a *number* argument from a value list.
270273

271274
```sql
272275
SELECT DATE_BUCKET(WEEK, (
273276
SELECT TOP 1 CustomerKey
274277
FROM dbo.DimCustomer
275-
WHERE GeographyKey > 100
276-
), (
277-
SELECT MAX(OrderDate)
278-
FROM dbo.FactInternetSales
279-
));
278+
WHERE GeographyKey > 100),
279+
(
280+
SELECT MAX(OrderDate)
281+
FROM dbo.FactInternetSales
282+
)
283+
);
280284
```
281285

282286
#### Specify numeric expressions and scalar system functions as number and date
283287

284-
This example uses a numeric expression ((10/2)), and scalar system functions (`SYSDATETIME`) as arguments for number and date.
288+
This example uses a numeric expression (`(10/2)`), and scalar system functions (`SYSDATETIME`) as arguments for *number* and *date*.
285289

286290
```sql
287-
SELECT DATE_BUCKET(WEEK, (10/2), SYSDATETIME());
291+
SELECT DATE_BUCKET(WEEK, (10 / 2), SYSDATETIME());
288292
```
289293

290294
#### Specify an aggregate window function as number
291295

292296
This example uses an aggregate window function as an argument for *number*.
293297

294298
```sql
295-
SELECT DISTINCT DATE_BUCKET(DAY, 30, CAST([ShipDate] AS DATETIME2)) AS DateBucket
296-
, FIRST_VALUE([SalesOrderNumber]) OVER (
299+
SELECT DISTINCT DATE_BUCKET(DAY, 30, CAST([ShipDate] AS DATETIME2)) AS DateBucket,
300+
FIRST_VALUE([SalesOrderNumber]) OVER (
297301
ORDER BY DATE_BUCKET(DAY, 30, CAST([ShipDate] AS DATETIME2))
298-
) AS First_Value_In_Bucket
299-
, LAST_VALUE([SalesOrderNumber]) OVER (
302+
) AS First_Value_In_Bucket,
303+
LAST_VALUE([SalesOrderNumber]) OVER (
300304
ORDER BY DATE_BUCKET(DAY, 30, CAST([ShipDate] AS DATETIME2))
301-
) AS Last_Value_In_Bucket
305+
) AS Last_Value_In_Bucket
302306
FROM [dbo].[FactInternetSales]
303-
WHERE ShipDate BETWEEN '2011-01-03 00:00:00.000'
304-
AND '2011-02-28 00:00:00.000'
307+
WHERE ShipDate BETWEEN '2011-01-03 00:00:00.000' AND '2011-02-28 00:00:00.000'
305308
ORDER BY DateBucket;
306309
GO
307310
```
@@ -311,13 +314,14 @@ GO
311314
This example uses a non-default origin value to generate the date buckets.
312315

313316
```sql
314-
DECLARE @date DATETIME2 = '2020-06-15 21:22:11';
315-
DECLARE @origin DATETIME2 = '2019-01-01 00:00:00';
317+
DECLARE @date AS DATETIME2 = '2020-06-15 21:22:11';
318+
DECLARE @origin AS DATETIME2 = '2019-01-01 00:00:00';
319+
316320
SELECT DATE_BUCKET(HOUR, 2, @date, @origin);
317321
```
318322

319-
## See also
323+
## Related content
320324

321-
- [CAST and CONVERT &#40;Transact-SQL&#41;](../functions/cast-and-convert-transact-sql.md)
325+
- [CAST and CONVERT (Transact-SQL)](cast-and-convert-transact-sql.md)
322326
- [Date and time types](../data-types/date-and-time-types.md)
323327
- [Date and time data types and functions (Transact-SQL)](date-and-time-data-types-and-functions-transact-sql.md)

0 commit comments

Comments
 (0)