Считайте разницу двух дат с учетом того, что каждый месяц имеет ТОЧНЫЕ 30 дней - PullRequest
0 голосов
/ 06 декабря 2011

Я думал, что это ясно, но не кажется так.Этот вопрос касается T-SQL (поскольку он помечен как tsql :))

Поэтому я не смог найти никакого готового решения для расчета моей проблемы.

Давайте предположим,у вас есть эти два dateTimes:

DECLARE @start DATETIME = '2011-01-01',
    @end DATETIME = '2011-04-15'

Разница между этими двумя датами в днях должна быть эквивалентна 105.

Расчет работает следующим образом: для каждого полного месяца добавьте 30 дней, дляостальные добавляют дни до достижения даты.

Я мог бы запрограммировать это, но это был бы огромный SQL-оператор, который я нахожу довольно уродливым.

Есть ли какое-то простое решениедля этого, как встроенная функция или что-то короткое?

Заранее спасибо.

Ответы [ 3 ]

1 голос
/ 06 декабря 2011

Это делает трюк?

;with dates as
(
SELECT
CAST ('2011-01-01' AS DATETIME) as start_date
,CAST('2011-04-15' AS DATETIME) as end_date
)
SELECT 
start_date
,end_date
,CASE WHEN DATEDIFF(MM,start_date,end_date) = 0 THEN DAY(end_date) - DAY(start_date) 
        WHEN DAY(start_date) = 1 THEN (30 * (DATEDIFF(MM,start_date,end_date))) + DAY(end_date) 
        WHEN DAY(start_date) <> 1 THEN  30 * DATEDIFF(MM,start_date,end_date) + (DAY(end_date) - DAY(start_date))
        END AS gap_in_days
FROM dates
0 голосов
/ 06 декабря 2011

Короткий ответ

Там нет встроенной функции, но вы можете довольно легко создать свою собственную для обработки преобразования даты и времени в int. Оттуда SQL, который вы должны будете написать, будет тривиальным.

Длинный ответ

Нет встроенной функции, которая будет делать это, вероятно, потому что каждый месяц не имеет 30 дней. :)

Вы можете начать с этого:

DECLARE @start DATETIME = '2011-01-01',
        @end DATETIME = '2011-04-15'

DECLARE @endConverted INT
SELECT @endConverted = DATEPART(month, @end) * 30 
                       + CASE 
                           WHEN DATEPART(DAY, @end) <= 30 
                             THEN datepart(DAY, @end)  
                           ELSE 30 
                         END

DECLARE @startConverted INT
SELECT @startConverted = DATEPART(MONTH, @start) * 30
                         + CASE
                             WHEN DATEPART(DAY, @start) <= 30
                               THEN DATEPART(DAY, @start)
                             ELSE 30
                           END

SELECT @endConverted - @startConverted

Это не красивый SQL, но он работает. Обратите внимание, что он возвращает 104 (потому что 15 дней - 1 день = 14 дней), но достаточно простой, чтобы привязать + 1 к концу окончательного выбора, если вы хотите обрабатывать ограниченные дни по-другому.

Обратите внимание, что математика здесь довольно легко может быть перенесена в функцию, которая позволит вам очистить ваш SQL. Предположим, вы создали функцию с именем GetDateTimeAsInt, в которой хранится математика; ваш SQL может быть таким простым, как

DECLARE @start INT = GetDateTimeAsInt('2011-01-01'),
        @end INT = GetDateTimeAsInt('2011-04-15')

SELECT @end - @start -- may need to add 1 here

В моем тестировании это похоже на работу. Он вернет тот же результат, что и функция DATEDIFF для диапазона дат, который вы указали в своем сообщении, но это потому, что есть 2 дня с 31 днем ​​и 1 день с 28, поэтому с января по апрель по 30 дней каждый. Если вы используете его с более широким диапазоном дат, вы начнете получать другие результаты с моим кодом от функции DATEDIFF.

Надеюсь, это поможет.

0 голосов
/ 06 декабря 2011

Я использую PERIODDIFF . Чтобы получить год и месяц даты, я использую функцию EXTRACT :

  SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM time)) AS months FROM your_table;

T-SQL

    SELECT DATEDIFF(dd, "2011-01-01","2011-04-15")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...