Вимогою в нещодавньому проекті було звітувати про те, коли ресурс буде повністю спожитий. Як і дата календаря виснаження, мене попросили показати час, що залишився в англійському форматі, на кшталт "1 рік, 3 місяці".
Вбудована DATEDIFF
функція
Повертає кількість ... вказаних меж частини дати, перекреслених між заданими датою початку та датою закінчення.
Якщо використовувати як-це, це може призвести до оманливих або заплутаних результатів. Наприклад, використання інтервалу РОКУ показало б, що 1999-12-31 (РРРР-ММ-DD) та 2000-01-01 є один рік один від одного, тоді як здоровий глузд говорить, що ці дати розділені лише на 1 день. І навпаки, використання інтервалу DAY 1999-12-31 та 2010-12-31 розділяється на 4118 днів, тоді як більшість людей бачать "11 років" як кращий опис.
Починаючи з кількості днів і обчислюючи місяці та роки звідти, було б схильним до помилок року та розміру місяця.
Мені стало цікаво, як це можна реалізувати в різних діалектах SQL? Приклад виводу включає:
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)
Я випадково використовую SQL Server 2008R2, але мені цікаво дізнатись, як інші діалекти впораються з цим.