W ostatnim projekcie wymagano podania, kiedy zasób zostanie w pełni wykorzystany. Oprócz daty wyczerpania kalendarza poproszono mnie o pokazanie pozostałego czasu w formacie angielskim, np. „1 rok, 3 miesiące do końca”.
Wbudowana DATEDIFF
funkcja
Zwraca liczbę ... określonych granic datapart przekroczonych między określoną datą początkową i końcową.
Jeśli zastosuje się go w takiej postaci, może to powodować mylące lub mylące wyniki. Na przykład użycie przedziału YEAR pokazałoby, że 1999-12-31 (RRRR-MM-DD) i 2000-01-01 są w odstępie jednego roku, podczas gdy zdrowy rozsądek mówi, że te daty są oddzielone tylko o 1 dzień. I odwrotnie, stosując przedział DAY 1999-12-31 i 2010-12-31 dzieli się 4018 dni, podczas gdy większość ludzi uważa, że „11 lat” to lepszy opis.
Począwszy od liczby dni i obliczania miesięcy i lat, podatne byłyby na błędy w roku przestępnym i wielkości miesiąca.
Zastanawiałem się, jak można to zaimplementować w różnych dialektach SQL? Przykładowe dane wyjściowe obejmują:
create table TestData(
FromDate date not null,
ToDate date not null,
ExpectedResult varchar(100) not null); -- exact formatting is unimportant
insert TestData (FromDate, ToDate, ExpectedResult)
values ('1999-12-31', '1999-12-31', '0 days'),
('1999-12-31', '2000-01-01', '1 day'),
('2000-01-01', '2000-02-01', '1 month'),
('2000-02-01', '2000-03-01', '1 month'), -- month length not important
('2000-01-28', '2000-02-29', '1 month, 1 day'), -- leap years to be accounted for
('2000-01-01', '2000-12-31', '11 months, 30 days'),
('2000-02-28', '2000-03-01', '2 days'),
('2001-02-28', '2001-03-01', '1 day'), -- not a leap year
('2000-01-01', '2001-01-01', '1 year'),
('2000-01-01', '2011-01-01', '11 years'),
('9999-12-30', '9999-12-31', '1 day'), -- catch overflow in date calculations
('1900-01-01', '9999-12-31', '8099 years 11 months 30 days'); -- min(date) to max(date)
Zdarza mi się używać programu SQL Server 2008R2, ale jestem zainteresowany, aby dowiedzieć się, jak poradzą sobie z tym inne dialekty.