W codziennej pracy bardzo często używamy funkcje daty i czasu , które są kluczowe w trakcie przeprowadzania analizy danych czy te tworzenia raportów. Bardzo często spotykamy się z problemem przeliczenia odpowiedniej daty jako początek zadanego okresu czyli początek roku, miesiąca, kwartału itp.

Standardowe wymagania dla zrealizowania tego celu jest użycie dwóch funkcji:

  • DateDiff()
  • DateAdd()

Obcinamy daty

Pierwszy dzień roku

Najpierw przejdziemy do pierwszego dnia roku. W celu spełnienia tego wymogu, używamy zarówno funkcji DateDiff(), jak i DateAdd().

SELECT DATEADD(year, DATEDIFF(year, 0, '2025-02-14 14:55:01.156'), 0) AS YearStart;

W wyniku dostajemy:
2025-01-01 00:00:00.000

Analogicznie przejdźmy do pierwszego dnia kwartału, miesiąca, pełnego dnia. Dodatkowo użyjmy początek godziny, minuty czy sekundy.

SELECT DATEADD(quarter, DATEDIFF(quarter, 0, '2025-12-24 17:58:26.667'), 0)  AS QuarterStart;
SELECT DATEADD(month, DATEDIFF(month, 0, '2025-12-24 17:58:26.667'), 0) AS MonthStart;
SELECT DATEADD(day, DATEDIFF(day, 0, '2025-12-24 17:58:26.667'), 0) AS DayStart;
SELECT DATEADD(hour, DATEDIFF(hour, 0, '2025-12-24 17:58:26.667'), 0) AS HourStart;
SELECT DATEADD(minute, DATEDIFF(minute, 0, '2025-12-24 17:58:26.667'), 0) AS MinuteStart;

Dostajemy analogicznie:

-- QuarterStart
-----------------------
2025-10-01 00:00:00.000

-- MonthStart
-----------------------
2025-12-01 00:00:00.000

-- DayStart
-----------------------
2025-12-24 00:00:00.000

-- HourStart
-----------------------
2025-12-24 17:00:00.000

-- MinuteStart
-----------------------
2025-12-24 17:58:00.000

Zróbmy teraz dla sekund:

--error: The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart.
select DATEDIFF(second, 0, '2025-12-24 17:58:26.667')

select DATEDIFF_BIG(second, 0, '2025-12-24 17:58:26.667')

--error Arithmetic overflow error converting expression to data type int.
SELECT DATEADD(second, DATEDIFF_BIG(second, 0, '2025-12-24 17:58:26.667'), 0) AS SecondStart;

W tym przypadku dla sekund dostajemy błąd. W przypadku DATEDIFF przekroczyliśmy zakres wartości INT jaką zwraca a funkcja. Musimy wiec użyć DATEDIFF_BIG, która zwraca wartość bigint.
W tym przypadku to zadziałało , ale gdy tą wartość podstawiamy do funkcji DATEADD uzyskamy kolejny błąd ponieważ ta funkcja nie przyjmuje argumentu bigint tylko int.

Co dalej …

W tym momencie z pomocą przychodzi nam funkcja DATETRUNC(), która od SQL Server 2022 pojawiła się do obsługi takich sytuacji.

Funkcja DATETRUNC() pomaga obciąć datę wejściową zgodnie z określoną precyzją. Jego składnia wygląda następująco:

DATETRUNC ( datepart , (input)date ) )

Tutaj datepart może mieć jedną z następujących wartości:

Poniżej mamy przykłady użycia tej funkcji.

DECLARE @input datetime2 = '2025-12-24 17:58:26.66712345';

SELECT DATETRUNC(YEAR, @input) AS YearStart;
SELECT DATETRUNC(QUARTER, @input) AS QuarterStart;
SELECT DATETRUNC(MONTH, @input) AS MonthStart;
SELECT DATETRUNC(DAY, @input) AS DayStart;
SELECT DATETRUNC(HOUR, @input) AS HourStart;
SELECT DATETRUNC(MINUTE, @input) AS MinuteStart;
SELECT DATETRUNC(SECOND, @input) AS SecondStart;

W rezultacie dostajemy:

YearStart
---------------------------
2025-01-01 00:00:00.0000000

QuarterStart
---------------------------
2025-10-01 00:00:00.0000000

MonthStart
---------------------------
2025-12-01 00:00:00.0000000

DayStart
---------------------------
2025-12-24 00:00:00.0000000

HourStart
---------------------------
2025-12-24 17:00:00.0000000

MinuteStart
---------------------------
2025-12-24 17:58:00.0000000

SecondStart
---------------------------
2025-12-24 17:58:26.0000000

Jak widać przy wyliczeniu sekund nie powstaje błąd.


Dariusz Brejnak

Od prawie trzydziestu lat jest pasjonatem informatyki, a zwłaszcza dziedzin dotyczących baz danych, hurtowni danych oraz ogólnie rozumianej tematyki BI. Jego druga pasja to fotografia http://dariuszbrejnak.pl